needle

数据集与模型

cactus-compute/needle

14MB端侧基础模型,支持工具调用与结构化提取。

项目简介

Needle 2 是一个高度压缩的45M参数模型,打包为单一14MB二进制,面向手机、可穿戴设备与机器人。它支持工具调用、设备使用与结构化提取,具备置信度门控,内存占用约28MB。Python包提供推理、LoRA微调与导出功能。

README 预览

\n\n# Needle 2\n\nNeedle 2 is an open 45M-parameter model for tool calling, device use and structured extraction. The whole model is a single 14MB binary that runs a full session in about 28MB of RAM. It is built on our Simple Attention Network findings, compressed to CQ2-bit with Cactus Quants, and baked into its own engine. On the benchmarks below, Needle 2 trades wins with other small models like FunctionGemma 270M, LFM2.5 230M and Apple FM, at 5x to 70x smaller, and 2 bits against their f16.\n\nThis repository is the Python package: inference, LoRA fine-tuning, and export. `pip install cactus-needle`, describe your tools, and call them from Python. The inference engine is fetched once from Hugging Face and cached; there is nothing else to build.\n\n- **Self-contained**: weights baked into a single 14MB engine; no separate model files to manage, and inference does no network.\n- **Simple contract**: tool calls come back as structured data, text in, JSON out; a byte-level grammar compiled from your schemas constrains every token.\n- **Confidence-gated**: every response carries a calibrated confidence score from a learned head; set a threshold, act above it, escalate below it.\n- **Tool retrieval**: declare a large catalogue and a built-in retrieval head renders only the top five tools per turn, with the grammar constrained to that subset.\n- **Bounded memory**: a 256-token sliding window with the tools pinned as KV sinks, so total memory stays near 28MB no matter how long the conversation runs.\n\nWeights: [huggingface.co/Cactus-Compute/needle2](https://huggingface.co/Cactus-Compute/needle2) · source: [github.com/cactus-compute/needle](https://github.com/cactus-compute/needle).\n\n\n\n## Simple Attention Network\n\nNeedle 2 is a Simple Attention Network, our dense small-model recipe: a Hadamard MLP in place of the FFN, GQA attention, engram key-value memory, and multi-lane hyper-connections. See the paper for the design and ablations: [arXiv:2607.18363](htt

常见问题 (5)

故障排除
安装 cactus-needle 3.0.5 后,如何修复 cactus_needle-3.0.2 wheel 的 'needle fetch' 404 错误?

失败的原因是 cactus-needle 3.0.5 请求 engine wheel 3.0.2,但 Hugging Face 仓库中只有 3.0.0 和 3.0.1。临时解决方法:降级到 3.0.4,该版本将 engine 固定为 3.0.1:

pip install --force-reinstall cactus-needle==3.0.4
needle fetch

代码修复方案是将 needle/agent/fetch.py 中的 ENGINE_VERSIONS[3] 从 3.0.2 改回已发布的 3.0.1 wheel,或者安装包含该修复的版本。另一种方法是将 3.0.2 的 wheel 上传到 Cactus-Compute/needle3 Hugging Face 仓库。

来源 Issue #142
故障排除
如何修复运行 needle finetune 时出现的 "unrecognized arguments: --layers" 错误?

不要将 --layers 传递给 needle finetune;该选项仅由过时的帮助文本展示,finetune 解析器并不支持它。请在不使用该选项的情况下运行微调,例如 needle finetune data.jsonl --checkpoint <path>。Rung 选择属于构建步骤:请使用 needle build --layers N。本地微调以完整的 20 层运行。如果过时的提示仍然出现,请更新到包含 CLI 帮助修复的版本。

来源 Issue #139
故障排除
如何修复复用 Needle generation=2 实例时,交替的连续请求中 `function_calls` 为空的问题?

出现这种情况是因为 complete()/_complete() 会将每次调用视为同一对话中的一个轮次。不相关的提示词会在历史记录中不断累积,导致置信度下降,并使工具调用与 function_calls: [] 交替出现。

对于相互独立的提示词,请在每次调用之间重置对话:

agent = needle.Needle(tools=[get_weather, send_message], generation=2)

for prompt in prompts:
    resp = agent._complete(prompt)
    print(resp["function_calls"], resp["confidence"])
    agent.reset()

agent.close()

或者,如果您安装的版本包含无状态模式,可以使用该模式:

agent = needle.Needle(
    tools=[get_weather, send_message],
    generation=2,
    stateless=True,
)

stateless=True 会在每次查询前自动重置。为每个独立请求创建并关闭一个全新的 Needle 实例也是一种有效的变通方法。只有当这些提示词确实属于同一对话时,才应在不重置的情况下复用该实例。

来源 Issue #138
故障排除
如何修复 Needle 初始化失败,Hugging Face 上 cactus_needle-3.0.2 的 wheel 返回 404 错误的问题?

失败的原因是 needle 请求引擎 wheel cactus_needle-3.0.2-py3-none-manylinux2014_x86_64.whl,但 Cactus-Compute/needle3 Hugging Face 仓库仅发布了 3.0.0 和 3.0.1 版本。请将 cactus-needle 升级到包含 fetch 修复的版本。如果尚未安装修复版本,可在本地将引擎固定为 3.0.1:

import pathlib, needle
p = pathlib.Path(needle.__file__).parent / "agent" / "fetch.py"
s = p.read_text()
p.write_text(s.replace("3.0.2", "3.0.1"))

然后重启 Python 进程/Colab 运行时,并重新初始化 needle.Needle()。或者,使用仍引用可用的 3.0.1 wheel 的软件包版本。

来源 Issue #146
故障排除
如何修复 Needle 将 "5 June 19:30" 中的小时解析为年份并将日期标记为 ungrounded 的问题?

这是 needle/__init__.py 中 _source_years 函数的一个正则表达式 bug。日/月模式使用了 (\d{1,4})(?![0-9A-Za-z]),因此 19:30 中的 19、14:00 中的 14 以及 7 pm 中的 7 都被错误地识别为年份。请升级到包含 issue #153 修复的版本。如果你需要立即打补丁,可以将年份末尾的前瞻断言(lookahead)改为拒绝时间后缀,例如:(\d{1,4})(?!\s*:\d{2}|\s*[ap]\.?m\.?(?![A-Za-z])|[0-9A-Za-z]),并使用不区分大小写的匹配。这样仍然允许类似 "5th September 42" 这样的短年份。作为临时变通方案,请写上明确的四位数年份,例如 "5 June 2026 19:30"。使用 needle._source_years("Book a table on 5 June 19:30") 进行验证,它应返回 set(),然后运行 pytest -q -m "not slow"。

来源 Issue #153