28
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

14MBのAIモデルは本当に動いた — DLL 1個・RAM 37MB・1回0.5秒、ただし日本語は0/5

28
Last updated at Posted at 2026-08-18

GitHub Trending に「14MB のモデル」が来ていました。

Cactus Compute の Needle 2 です。45M パラメータで、ツール呼び出しに特化しています。週で +3,627 スター伸びていました。

14MB というのは、画像1枚くらいのサイズです。しかも「モデルファイル」ではなく、エンジンごと入って14MBだといいます。

The whole model is a single 14MB binary that runs a full session in about 28MB of RAM.
(モデル全体が単一の 14MB バイナリであり、セッション全体を約 28MB の RAM で実行する)

本当なのか、Windows で動かして測りました。

動きました。 DLL 1個、RAM 37MB、1回 0.5 秒です。

ただし、日本語は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 バイト)
依存パッケージ ゼロで動くimport needle のみ)
1回の推論 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個で本当に動きます。 最後の行だけが厄介ですが、これは回避できます。


DLL 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 のような別のモデルファイルはありません。これ1個に重みまで入っています。

そして、この DLL さえあれば Python 側の依存はゼロでした。cactus-needlepip しか入っていない 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 秒
2回目以降(キャッシュあり) 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"}]
}
項目 実測
1回の推論 0.42〜0.66 秒
decode 155〜177 tok/s
ピークRAM 36〜43MB

公称 28MB は少し超えました。 ただしこれは Windows の x86_64 で Python 経由の数字です。公称値が想定しているのは組み込み側なので、そのまま比較はできません。

ここで1つ面白いことが起きました。

依存を全部入れた状態で同じコードを走らせると、ピークRAM が 94.6MB になりました。依存なしだと 37.8MB です。

構成 ピークRAM
依存あり(huggingface_hub 等を import) 94.6MB
依存なし(cactus-needle のみ) 37.8MB

2.5倍違います。読み込んでいる DLL は同じものです。差は Python 側に import したライブラリの分でした。peak_ram_mb はエンジン内部だけでなく、プロセス全体を見ているようです。

「28MB で動く」という設計を活かしたいなら、同じプロセスに何を import しているかのほうが効いてきます。


ツールは、ちゃんと選べている

5つのツールを登録して、英語で5問投げました。定義はデコレータ1つです。

@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 bob@example.com 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 で完結する意味は薄れます。


難点は、入れるところ

ここまで「DLL 1個で動く」と書いてきましたが、素直に 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 で、終端を含むと実質 259 文字までしか使えません。1文字足りずに落ちています。

最初は自分の作業ディレクトリが深いせいかと思って、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 は魅力
組み込み・オフライン端末 向いている。 DLL 1個で完結する
日本語の入力を直接受ける 向かない。 0/5

小さい LLM ではなく、ツールを選ぶ部品。そう見ると納得できます。ChatGPT の代わりにはなりません。

なお公式のベンチマークでも、勝ち負けは分かれています。BFCL v4 single-turn は 42.6% で、LFM2.5 230M の 60.8% に負けています。サイズが 5〜70 分の1という条件付きの勝負であって、「小さいのに全部勝つ」ではありません。


まとめ

  • 14MB は本当。 エンジンの実体は libneedle.dll 1個(14,301,696 バイト) で、重みごと入っている
  • Python の依存はゼロで動く。 DLL さえキャッシュにあれば、推論でネットワークにも触らない
  • 実測は 0.42〜0.66秒 / 155〜177 tok/s / ピークRAM 36〜43MB
  • 同じプロセスに何を import するかでRAMが2.5倍変わる(37.8MB → 94.6MB)。小ささを活かすなら周りも軽くする
  • ツール選択は英語で 4/5、平均 0.58 秒
  • 日本語は 0/5。 しかも説明文を日本語にすると confidence が 0.03 から 0.89 に上がる。 間違ったまま自信だけ上がるので、信頼度で弾けない
  • pip install は venv を 570MB にし、Windows では失敗するMAX_PATH 260文字)。--no-deps で回避でき、推論はそれで足りる

画像1枚のサイズで、ツールを選ぶモデルが動く。 ここは素直に驚きました。日本語が通らないので用途は限られますが、英語のコマンドを受けて機器を操作するような使い方なら、今すぐ試せます。


参考

※ 引用は原文と日本語訳を併記しています。訳は読みやすさを優先しているので、正確な表現は原典をご確認ください。

関連記事


JQITのエンジニアの95%以上は未経験からの採用です。
よければコーポレートサイトにも遊びに来てください。

コーポレートサイト

エンジニア採用も行っています。もしご興味あれば覗いてみてください。

採用サイト

28
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?