GitHub Trending 上出現了「14MB 的模型」。
這是 Cactus Compute 的 Needle 2。它有 45M 參數,專注於工具呼叫。一週增加了 +3,627 顆星。
14MB 大概只有一張圖片的大小。更重要的是,它不是只有「模型檔」,而是連整個引擎一起算進去也只有 14MB。
The whole model is a single 14MB binary that runs a full session in about 28MB of RAM.
(整個模型是一個單一的 14MB 二進位檔,完整執行一個 session 大約只需 28MB 的 RAM)
這是真的嗎?我在 Windows 上實際跑了一次並測量。
真的能跑。 1 個 DLL、RAM 37MB、每次 0.5 秒。
但是,日文 5 題全錯。而且信心值還有 0.89。
驗證對象:https://github.com/cactus-compute/needle(Apache-2.0)
環境:Windows 10 Home 19045 / AMD Ryzen(16 執行緒)/ Python 3.12.3
| 項目 | 實測 |
|---|---|
| 引擎實體 | 只有 libneedle.dll 1 個(14,301,696 位元組) |
| 相依套件 | 0 個也能跑(只要 import needle) |
| 單次推論 | 0.42〜0.66 秒 |
| decode | 155〜177 tok/s |
| 峰值 RAM | 36〜43MB |
| 工具選擇(英文・5 題) | 4/5 |
| 工具選擇(日文・5 題) | 0/5(弱點) |
pip install |
venv 會膨脹到 570MB,而且在 Windows 上會失敗 |
14MB 的二進位檔 1 個真的就能跑。 只有最後那個問題比較麻煩,但可以避開。
先追查實體到底在哪裡。答案寫在 needle/agent/fetch.py 裡。
HF_REPO = "Cactus-Compute/needle2"
ENGINE_VERSION = "2.0.2"
PLATFORMS = ("macos-arm64", "linux-x86_64", ..., "windows-x86_64", "windows-arm64",
"android-arm64", "ios-arm64", ..., "wasm")
它會從 Hugging Face 下載各平台對應的二進位檔。 其中包含 windows-x86_64,代表 Windows 支援是真的。
| 項目 | 內容 |
|---|---|
| 下載的東西 | cactus_needle-2.0.2-py3-none-win_amd64.whl(13MB) |
| 取出的檔案 | 裡面的 libneedle.dll |
| 儲存位置 | ~/.cache/cactus-needle/2.0.2/libneedle.dll |
| 覆寫方式 | 環境變數 NEEDLE_LIB_PATH |
我把下載下來的檔案量了一下。
14301696 bytes
14,301,696 位元組。大約 14MB。 沒有像 .gguf 那樣另外的模型檔。權重也都包含在這一個檔案裡。
而且只要有這個 DLL,Python 端的相依性就等於 0。只裝 cactus-needle 和 pip 的 venv 就能動。
Package Version
------------- -------
cactus-needle 2.0.6
pip 24.0
import : 0.024 s
Needle() init : 0.158 s
first run : 0.533 s
連 huggingface_hub 都沒裝。看原始碼可知,只要快取裡有 DLL,就直接丟給 ctypes.CDLL()。之後就不再碰網路。
不過,把它理解成「完全不用下載」就錯了。 官方寫的是 inference does no network(推論不使用網路)。第一次還是得把引擎抓下來,所以時間會不同。
| 狀態 | Needle() 初始化 |
|---|---|
| 第一次(含下載 DLL) | 5.250 秒 |
| 第二次以後(快取已存在) | 0.158〜0.170 秒 |
呼叫時,輸出裡就會帶計測值,不用自己另外測。
{
"type": "respond",
"reasoning": "Alarm set; confirm.",
"confidence": 0.6804,
"decode_tps": 167.1,
"peak_ram_mb": 38.3,
"results": [{"tool": "set_alarm", "at": "7:30"}]
}
| 項目 | 實測 |
|---|---|
| 單次推論 | 0.42〜0.66 秒 |
| decode | 155〜177 tok/s |
| 峰值 RAM | 36〜43MB |
官方宣稱的 28MB 稍微超過了一點。不過這是 Windows x86_64、透過 Python 呼叫得到的數字。官方數字假設的是嵌入式側,所以不能直接硬比。
這裡有個有趣的現象。
在把所有相依都裝進去的狀態下跑同一段程式,峰值 RAM 會變成 94.6MB。如果不裝相依,只有 37.8MB。
| 組態 | 峰值 RAM |
|---|---|
有相依(import huggingface_hub 等) |
94.6MB |
無相依(只有 cactus-needle) |
37.8MB |
差了 2.5 倍。載入的 DLL 是同一個,差別來自 Python 端 import 的函式庫。peak_ram_mb 看起來不只是引擎本體,而是整個 process。
如果想發揮「28MB 就能跑」的設計優勢,同一個 process 裡 import 了什麼更關鍵。
我註冊了 5 個工具,用英文丟了 5 題。定義只要一個 decorator。
@needle.tool
def get_weather(city: str):
"Get the current weather for a city."
return {"tool": "get_weather"}
| 提示詞 | 期待結果 | 實際結果 |
|---|---|---|
| wake me up at 7:30 tomorrow | set_alarm | OK |
| what is the weather in Osaka? | get_weather | OK |
| play some Miles Davis | play_music | OK |
| how much is 100 dollars in yen? | convert_currency | MISS(選成 get_weather) |
| email [email protected] about the meeting delay | send_email | OK |
4/5,平均 0.58 秒。 以 45M 參數來說,我覺得已經相當不錯。
錯的是匯率換算,它選成了 get_weather。
這點是我最想知道的。
同樣的配置改成日文後,結果如下。
| 提示詞 | 期待結果 | 實際結果 |
|---|---|---|
| 大阪の天気を教えて | get_weather | MISS |
| 明日の7時に目覚ましをセットして | set_alarm | MISS |
結果是 0/2。看內容的話,會變成這樣:
{
"type": "call",
"reasoning": "No tool available for sending messages or sharing content.",
"confidence": 0.0313,
"results": []
}
它把「大阪の天気を教えて」解讀成了發送訊息的請求。
我以為是工具說明都是英文所以才會這樣,於是把說明也改成日文再測一次。
@needle.tool
def get_weather(city: str):
"指定された都市の現在の天気を取得する。"
return {"tool": "get_weather", "city": city}
README 裡寫了這句,所以說明文字應該是有效的。
Needle reads your tool descriptions to decide what to call and how to fill arguments, so describing them well is the whole game.
(Needle 會讀取你的工具描述,來決定要呼叫哪個工具,以及如何填入參數,所以把描述寫好就是全部)
結果如下。
| 提示詞 | confidence | 模型判斷 |
|---|---|---|
| 大阪の天気を教えて | 0.8914 | No tool available for sending messages or sharing content. |
| 東京の天気は? | 0.836 | Social media interaction not supported by any tool. |
| 7時30分にアラームをセットして | 0.2302 | No tool available for sharing content. |
0/3。甚至 confidence 還上升了。
英文說明時是 0.03。改成日文後變成 0.89。 判斷一樣錯,但只是信心值變高了。
這很麻煩。Needle 有回傳信賴度的機制,README 也預期可以用「低分就擋下來」。但日文情境下,這個門檻根本不會正常工作。
我認為,拿 45M 參數的模型去期待多語言能力,本來就有點勉強。不過這不只是「日文精度變差」,而是「錯得很有自信」,性質不太一樣。
如果要用日文,只能先在送進 Needle 前轉成英文。但如果都要加翻譯層,那 14MB 完成一切的優勢就會大打折扣。
前面雖然寫著「只靠 1 個 DLL 就能跑」,但直接 pip install 的話並不是這樣。
pip install cactus-needle
venv 會從 17MB 膨脹到 570MB,而且還會報錯失敗。
ERROR: Could not install packages due to an OSError: [Errno 2] No such file or directory:
'C:\nd\venv\Lib\site-packages\orbax\checkpoint\experimental\v1\_src\testing\compatibility\
checkpoints\v0_checkpoints\composite_checkpoint\checkpoint_metadata_missing\
pytree_checkpointable_missing_metadata\state\ocdbt.process_0\d\60c4009561fe85efe8a0afa099989378'
我把這條路徑數了一下。
failing path length: 260
LongPathsEnabled = 0
剛好 260 個字元。 Windows 的 MAX_PATH 是 260,包含結尾字元的話,實際可用空間還更少。就差一個字元而已,所以失敗。
一開始我還以為是工作目錄太深,所以把位置改到 C:\nd 這種極短路徑。結果還是在同一個地方失敗。 兇手不是安裝位置,而是套件內容本身。
把膨脹後的內容量一下:
| 套件 | 大小 |
|---|---|
jaxlib |
242MB |
scipy |
115MB |
tensorstore |
35MB |
numpy |
34MB |
jax |
30MB |
只有 jaxlib 和 scipy 就已經 357MB。宣告的相依裡還有 jax / flax / optax。這是機器學習訓練端的整套堆疊。
看過套件內容後就明白了。
needle/model/finetune.py ← 訓練
needle/model/quantize.py ← 量化
needle/model/export.py ← 匯出
它把微調與量化的程式都一起包進來了。 這些部分會用到 JAX。即使你只想做推論,也會一起被裝進來。
解法很簡單:
pip install --no-deps cactus-needle
Successfully installed cactus-needle-2.0.6
套件本體只有 479KB。這樣就能 import needle,而且推論也能正常運作(本文的所有測試都是這種配置)。如果不打算微調,根本不需要 JAX。
我的結論如下。
| 場景 | 怎麼用 |
|---|---|
| 英文、固定工具呼叫 | 適合。 0.5 秒 / 37MB 很有吸引力 |
| 嵌入式、離線裝置 | 適合。 只靠 1 個 DLL 就能完成 |
| 直接接受日文輸入 | 不適合。 0/5 |
它不是小型 LLM,而是用來選工具的零件。這樣看就比較合理了。它不會取代 ChatGPT。
另外,官方基準也顯示它有明顯的勝負分界。BFCL v4 single-turn 是 42.6%,輸給了 LFM2.5 230M 的 60.8%。這是在尺寸只有 5 到 70 分之 1 的前提下比賽,不是「小很多但全贏」。
libneedle.dll 1 個(14,301,696 位元組),權重也包含在裡面pip install 會讓 venv 膨脹到 570MB,且在 Windows 上失敗(MAX_PATH 260 字元)。用 --no-deps 可以避開,而推論本來就足夠只有一張圖片大小,卻能讓一個會選工具的模型跑起來。 這點真的讓人驚訝。雖然日文不行,應用範圍有限,但如果是接收英文指令來操作設備這類用途,現在就可以試試看。
參考
※ 引用保留原文與中文翻譯並列。翻譯以易讀為優先,請以原典為準。