onw — 俺のNPUがこんなに動くわけない
日本語 | English ・ 更新履歴 ・ 技術解説(NPU で初めて動かした 4 つ、MoE・SSD・画像エンコーダーの仕組み) ・ LFM を自分で変換
LLM を Intel NPU だけで 動かす小さなエンジンです。MoE(専門家混合)モデルや Gated DeltaNet 系のハイブリッドモデル、 画像入力にも対応し、OpenAI 互換 API サーバーとブラウザのチャット画面を備えています。 llama.cpp と GGUF の関係と同じく、エンジンとモデルは別々にダウンロードします。エンジンは一つ、コマンドも一つで、 変換済みのモデルならどれでも動きます。
インストール(コマンドを 1 行貼るだけ)
Intel Core Ultra(NPU 付き)の PC なら、次の 1 行で入ります(詳しい条件は下の「必要なもの」)。
Windows
- スタートメニューで「PowerShell」と入力し、「Windows PowerShell」を開きます(管理者として開く必要はありません)。
- 次の 1 行をコピーして貼り付け、Enter を押します。
irm https://huggingface.co/ryugyosoft/onw/resolve/main/install.ps1 | iex
onw が %LOCALAPPDATA%\onw にダウンロードされ、セットアップの黒い画面が開きます。Python が見つからない場合は
「Install Python 3.12 ... [Y,N]?」と聞かれるので Y を押してください。数分で終わり、タスクトレイ(画面右下)に
onw のアイコンが出て、モデルを選ぶウィンドウが開きます。
Ubuntu
端末(Ctrl+Alt+T)を開き、次の 1 行を貼り付けて Enter を押します。途中で必要な部品を入れるために、ログイン パスワードを 1 回聞かれます。
curl -fsSL https://huggingface.co/ryugyosoft/onw/resolve/main/install.sh | bash
onw は ~/onw に入り、画面右上に onw のアイコンが出ます。
貼り付ける前に中身を確認したい場合は、install.ps1/install.sh を開いて読めます。 新しい版が出るとトレイと onw ウィンドウに通知が出て、ボタン 1 つで更新できます(同じコマンドをもう一度実行しても更新できます)。
必要なもの
- Intel Core Ultra を搭載した PC(NPU 付き。Core Ultra シリーズ 1/2、Lunar Lake など)
- Windows 11、または Ubuntu 22.04 以降
- Ubuntu では NPU ドライバー(linux-npu-driver)1.38 以降。それより古いドライバーでは LFM2 系(自分で変換して使う場合)の前半の層が NPU 上で正しく計算されず、回答が途中から空になります(特殊トークンを出し続ける。Lunar Lake で確認、1.38 で解消)。版は
dpkg -l | grep -i npuで確認できます。 - 空き容量:エンジン約 1 GB + モデル 4〜17 GB(どのモデルを使うかによります)
- インターネット接続(最初のダウンロードのとき)
Python や git の知識は要りません。Python が入っていなければ、途中で入れるか聞かれます(Windows)。
使い方
モデルを選んでダウンロード
開いた onw ウィンドウ の「モデル」タブに、使えるモデルの一覧(サイズ、必要なメモリ、この PC で足りるか)が 出ます。迷ったら Gemma 4 E4B(画像も読める・使用メモリ約 6 GB)がおすすめです。16 GB の PC でも大きいモデルを試すなら Qwen3.6-35B-A3B(エキスパートを SSD から読んで動きます)。 選んで「ダウンロード」を押すと、進み具合がバーで表示されます。
- 保存先は「保存先」の「変更…」で好きなドライブにできます(C ドライブが狭いときなど)。
- すでにモデルを別の場所に持っている場合(
hf downloadで入れた、自分で変換した など)は、「ほかの場所」の「追加…」で そのフォルダ(またはモデルのフォルダをまとめて入れた親フォルダ)を選べば一覧に出ます。コピーは不要です。 - 画面の言語は OS に合わせて日本語・英語・中国語(簡体字)から選ばれます。「設定」タブの「言語」で変えられます。
読み込んで使う
「サーバー」タブでモデルを選んで「ロード」を押します。初回だけ NPU 向けの準備(コンパイル)に 10〜30 分ほど かかります(モデルと PC によります。テスト機では Gemma 4 E4B が約 4〜11 分、Qwen3.6-35B-A3B が約 7 分、Qwen3.5-9B が約 13 分)。 状態が「動作中」になるまで待ってください。その間も PC は普通に使えます。2 回目以降は結果が保存されているので 20 秒ほどで起動します(コンテキスト長を変えても、コンパイルし直しはありません)。
- すぐ試す:「チャット」でブラウザにチャット画面が出ます。「検証ページ」では、速度や画像のテストを一括で実行できます。
- 他のアプリから使う:onw は OpenAI 互換 API です。OpenAI の API に対応したアプリ(チャットアプリ、エディターの
拡張機能、自作のプログラムなど)で、base URL に
http://localhost:8000/v1、モデル名にウィンドウに表示される 名前を入れれば使えます。API キーの欄は、設定していなければ何を入れても構いません。
あとは、タスクトレイ(Ubuntu は右上)の onw アイコンを右クリックすれば、いつでもウィンドウやチャットを開けます。 ウィンドウを閉じてもサーバーは動き続けます。止めるときはメニューの「アンロード」、onw ごと終わるときは「終了」です。

モデル一覧
| onw モデル | アーキテクチャ | 入力 | NPU 3720 生成速度 | ダウンロード | 使用メモリ |
|---|---|---|---|---|---|
| ryugyosoft/gemma-4-E4B-it-onw | gemma4(検証済みの Gemma NPU グラフを取り込み) |
テキスト+画像 | 7.2 tok/s | 4.3 GB | 約 6 GB(画像処理中 8.5 GB) |
| ryugyosoft/Qwen3.5-9B-onw | qwen3_5(Gated DeltaNet+ゲート付きアテンション、dense) |
テキスト+画像 | 4.1 tok/s | 5.3 GB | 約 11 GB |
| ryugyosoft/Qwen3.6-REAP-18B-A3B-onw | qwen3_5_moe、256 個中 128 個のエキスパートを残す(REAP) |
テキスト+画像 | 6.8 tok/s | 9.6 GB | 約 12 GB |
| ryugyosoft/Qwen3.6-35B-A3B-onw | qwen3_5_moe(Gated DeltaNet+ゲート付きアテンション+MoE 256 個から 8 個+共有エキスパート) |
テキスト+画像 | 6.8 tok/s | 17 GB | 約 20 GB(SSD から読めば 8〜13 GB) |
| ryugyosoft/gpt-oss-20b-onw | gpt_oss(OpenAI gpt-oss-20b:MoE 32 個から 4 個、attention sink、YaRN、harmony 形式。エキスパートはチャネル単位 INT4) |
テキスト | 8.5 tok/s | 11.4 GB | 約 12 GB |
| ryugyosoft/gpt-oss-20b-int8-onw | 同上、エキスパート INT8(bf16 に近い精度) | テキスト | 6 tok/s | 21 GB | 約 21 GB(SSD から読めば 8〜13 GB) |
使用メモリは、テスト機(Core Ultra 9 285HX、NPU 3720)で、64 トークン処理なし・画像エンコーダーは使ったら解放(メモリ 24 GB 未満の PC の既定)で測ったプロセスのピークです。onw ウィンドウの「メモリ目安」は、この値にその PC の設定 (コンテキスト長、64 トークン処理、エキスパートのメモリ)を反映した目安です。メモリが足りない PC では、Qwen3.6 系の エキスパートを SSD に置いたまま動かせます(設定の「エキスパートのメモリ」。仕組みは技術解説)。
先読み検証は、16 トークンの検証ブロックが十分安く済むモデル(Qwen3.5-9B、Gemma、LFM 系)で自動的に使われます。
思考モードのあるモデル(Qwen、LFM2.5)は、既定では考えずに答えます(チャット画面の「思考モード」、API の
chat_template_kwargs: {"enable_thinking": true} または reasoning_effort で考えさせられます)。gpt-oss は常に考えますが、
思考は思考モードのときだけ返します。思考は回答とは別に、API では reasoning_content、チャット画面では折りたためる
「思考」欄に出ます。
どのモデルも会話の状態をターン間で保持するので、画像付きの会話でも 2 ターン目は新しいメッセージだけを処理します(約 2 秒)。
LFM 系は自分で変換して使う
LiquidAI の LFM2.5-2.6B と LFM2-8B-A1B も onw で動きますが、変換済みのモデルは配布していません。LFM のライセンス (LFM Open License v1.0)は、年間売上 1000 万ドル以上の法人による商用利用を対象外にしているためです。元のモデルを Hugging Face から取得して、手元で変換してください(onw だけで変換でき、1〜数分です)。手順は LFM を自分で変換 にあります。AI アシスタントにそのページを読ませれば、そのまま実行できる形で 書いてあります。
| モデル(自分で変換) | アーキテクチャ | 入力 | NPU 3720 生成速度 | 変換後の大きさ | 使用メモリ |
|---|---|---|---|---|---|
| LiquidAI/LFM2.5-2.6B | lfm2(短い畳み込み+GQA、dense) |
テキスト | 12〜13 tok/s(コード修正・要約では先読み検証で 29〜34) | 1.5 GB | 約 4.3 GB |
| LiquidAI/LFM2-8B-A1B | lfm2_moe(短い畳み込み+GQA+MoE 32 個から 4 個) |
テキスト | 16〜17 tok/s(コード修正・要約では先読み検証で 29〜43) | 4.0 GB | 約 5 GB |
サーバー(OpenAI 互換 API)
他のアプリからは base URL に http://localhost:8000/v1、モデル名にウィンドウに表示される名前を指定します。
GET / でサーバーの案内(JSON)、/health でモデルの読み込み完了を確認できます。CORS は開放済みで、LAN に公開する
場合は API キー(--api-key または設定画面)で /v1 を保護できます。動作確認用に、チャット画面(/chat)と、
テキスト・先読み検証・2 ターン会話・画像の検証を一括実行して速度を表にする検証ページ(/check)もあり、どちらも
トレイのメニューとウィンドウから開けます。NPU ドライバーがない環境では CPU で動きます。
ツール呼び出し(function calling)にも対応しています。OpenAI と同じく tools を渡すと、モデルが呼び出しを決めたときは
finish_reason: "tool_calls" と message.tool_calls が返り、ストリーミングでも同じ形で届きます。ツールの結果は
role: "tool" のメッセージで返してください。tool_choice は "auto"(既定)、"none"、関数の指定(そのツールだけを
見せる)に対応します("required" は強制できません)。Qwen3.5/Qwen3.6、Gemma 4、LFM2.5、gpt-oss で確認済みです(モデルごとの
書式の違いは onw が吸収します)。
response_format(json_object/json_schema)は指示を足すだけのベストエフォートで、出力の形は保証しません。n は 1 のみ
(2 以上は 400)、logprobs は null です。エラーは OpenAI と同じ {"error": {"message", "type", ...}} の形で返します。
http(s) の画像 URL は公開アドレスのものだけ取りに行きます(ローカルネットワークの URL は data: URL で送ってください。
ONW_ALLOW_LOCAL_IMAGES=1 で許可)。
onw コマンドと設定
onw serve MODEL [--port 8000] [--host 0.0.0.0] [--api-key KEY] [--context 4096] [--device NPU|CPU] [--no-pld] [--open]
onw chat MODEL [--think] [--context 4096] # ターミナルでチャット
onw tray # 常駐アプリ(setup が起動するもの)
onw window [--tab models] # モデル管理・サーバー操作・設定のウィンドウ
onw convert HF_DIR OUT_DIR [--compact] [--prune SAL.json --keep 0.5] [--graphs-only]
onw list # 対応アーキテクチャ
設定を変えたときに何が必要か:
| 設定 | 変え方 | 再コンパイル |
|---|---|---|
| temperature、top_p、top_k、繰り返し抑制(repetition / presence / frequency penalty)、max_tokens、stop、seed、思考モード | リクエストごと(API またはチャット画面) | 不要 |
| ポート、待ち受けアドレス、モデル、デバイス、先読み検証のオン/オフ | サーバーのオプション/設定画面、再起動(約 20 秒) | 不要 |
コンテキスト長(--context、既定 32K、モデルの最大まで) |
サーバーのオプション/設定画面 | 不要(KV キャッシュの上限が変わるだけ) |
| 64 トークン処理(Gemma) | ONW_S64=1/0/設定画面 |
初回のみ |
| エキスパートのメモリ(Qwen3.6 系。上限を超える分は SSD から読む) | ONW_EXPERT_GB=5/設定画面 |
不要 |
| NPUW 重み共有(試験的。auto は Lunar Lake 以降でオン、MoE モデル(LFM2・Qwen3.6)は対象外:重みを 1 コピーにしてメモリとコンパイル時間を削減) | ONW_NPUW=1/0/設定画面 |
初回のみ |
| MoE モデルでも NPUW 重み共有(実験的、既定オフ。1 トークン用と 16 トークン用で重みを共有) | ONW_NPUW_MOE=1/設定画面 |
初回のみ |
NPUW の非同期実行 NPUW_FUNCALL_ASYNC(実験的、既定オフ) |
ONW_NPUW_ASYNC=1/設定画面 |
初回のみ |
コンパイルキャッシュを重みなしで保存 CACHE_MODE=OPTIMIZE_SIZE(実験的、既定オフ。NPUW 使用時のみ) |
ONW_CACHE_SIZE=1/設定画面 |
初回のみ |
| ブロックサイズ、画像サイズ、量子化 | onw convert(技術解説の「モデルを小さくする」) |
必要(変換し直し) |
KV キャッシュは INT8 で、会話が実際に使った長さの分だけメモリ(1K トークンあたり 8〜16 MB)と計算がかかります。 コンテキスト長は「そこまで伸ばしてよい上限」なので、大きくしても短い会話は遅くなりません(仕組みは技術解説)。
MODEL には onw 形式のモデルフォルダか Hugging Face のリポジトリ ID を指定します(ID の場合は ./models に
ダウンロードされ、途中から再開できます)。onw コマンドは初回の setup/start のあと .venv に入ります
(Windows は .venv\Scripts\onw、Linux は source .venv/bin/activate)。任意の環境に入れる場合は
pip install -e . --extra-index-url https://storage.openvinotoolkit.org/simple/wheels/pre-release です。
上級者向けの入手方法
hf download ryugyosoft/onw --local-dir onw(Hugging Face CLI)やgit clone https://huggingface.co/ryugyosoft/onwでも入手できます。その後、フォルダ内のsetup.bat(Windows)/bash setup.sh(Ubuntu)を実行してください。- モデルは onw ウィンドウからのダウンロードをおすすめします。自分で取得する場合は
hf download ryugyosoft/モデル名を使ってください。Git LFS なしでgit cloneすると、重みの代わりに約 130 バイトの「ポインタ」ファイルしか 入りません(onw はこれを検出し、直し方を表示して止まります)。 - コンソールで一度だけ起動したいときは
start.bat モデル名(Ubuntu はbash start.sh モデル名)。
構成
| ファイル | 内容 |
|---|---|
onw/ir.py |
グラフ部品:量子化線形層、RMSNorm(FP16 で溢れない前処理つき)、RoPE/部分 RoPE、ホスト管理の KV キャッシュ上のアテンション、エキスパート枠、Gated DeltaNet(1 トークン用の行列形式、ブロック倍々の厳密な逆行列によるチャンク並列形式) |
onw/runtime.py |
区間の実行、命名規則による状態管理(KV の行、畳み込み窓、再帰状態)、エキスパートの結び付け、MRoPE、スライディング窓マスク、ホスト側の表引き、先読み検証のための正確な巻き戻し、コンパイル経路の自動切り替え |
onw/paged.py、onw/kvcache.py |
読み込み時に区間をアテンションの位置で切り分け、ページ化した INT8 KV キャッシュと塊ごとのアテンション(オンライン softmax で合成) |
onw/store.py、onw/xio.py |
エキスパートの保管(全部メモリ/SSD から読む LRU キャッシュ)、OS のキャッシュを通さない直接読み込み |
onw/chat.py |
生成ループ:画像(Qwen/Gemma)、サンプリング、停止文字列、先読み検証(正確な巻き戻し、再帰状態を持つモデルでは遅延やり直し、効く場合だけ自動で有効)、ターン間の差分処理 |
onw/models/ |
アーキテクチャごとの組み立て定義:lfm2_moe(dense の lfm2 も)、qwen3_5_moe(dense と MoE)、qwen_vision、gemma4、gpt_oss |
onw/hub.py、onw/server.py、onw/web/ |
モデルのダウンロードと LFS 対策、OpenAI 互換サーバー、チャット画面(/chat)、検証ページ(/check) |
onw/app.py、onw/tray.py、onw/manager.py、onw/update.py、onw/i18n.py |
onw ウィンドウ(モデル/サーバー/設定)、トレイアイコン、ウィンドウの裏側(ローカル API)、自動更新、表示言語 |
setup.*、install.*、find_python.bat |
インストーラー(Python の検出と winget) |
check_ref.py、check_vision.py、test_*.py、probe_segments.py、prof_*.py、mem_*.py、bench_*.py |
元の HF モデルとの比較、生成・画像・複数ターンの検証、区間ごとの NPU と CPU の比較、速度・メモリ計測 |
注意点と制限
- コンテキスト長の既定は 32K トークンで、モデルの最大(Qwen3.5/3.6 は 262K、Gemma 4 E4B は 128K)まで設定できます。 長い会話では 1 トークンごとのアテンションの計算が長さに比例して増えます。Qwen の画像は 512×512(256 トークン)に縮小し、Gemma の画像は縦横比を保ちます (最大 280 トークン)。
- エキスパートはチャネル単位 INT4(四捨五入量子化)です。確認した範囲では、最初のトークンのロジットは bf16 との差が 約 33% で、1 位の予測は一致しました。回答は自然ですが、数トークン先から言い回しが bf16 モデルと分かれます。
- 16 トークンより大きいプロンプトブロック(Gemma の 64 トークン版)は RAM 24 GB 以上のときだけ読み込みます
(
ONW_S64=1/0で強制)。 - OpenVINO のプレリリース版(2026.5.0b1。OpenVINO の pre-release 索引から入ります)が必要です。NPU 3720(Windows 11)と NPU 4000(Lunar Lake、Ubuntu、 メモリ 16 GB)で全モデルの動作を確認しています。NPU ドライバーがない環境では CPU で動きます。
ライセンス
コードは Apache 2.0。変換済みモデルは元のモデルのライセンスに従います(各モデルのリポジトリを参照)。