NobodyWho: llama.cpp を Kotlin・Swift・Flutter・Godot から叩くための多言語バインディング
NobodyWho is an inference engine that lets you run LLMs locally and efficiently on any device.
ひと目でわかる
- これは何?
- NobodyWho は GGUF 形式の LLM を端末上で動かす推論エンジンで、Rust 実装のコアに Kotlin、Swift、Python、Flutter、React Native、Godot の各バインディングを被せている。llama.cpp のラッパーとして何を肩代わりし、どこで自前実装に戻すべきかを見る。
- 誰に向いている?
- 採用を検討すべきなのは、モバイルアプリやゲーム内にチャット UI を組み込み、モデルの配布まで含めて自前で抱えたいチームだ。特に Godot 4.5 以降で AssetLib から導入できる点は、ゲームエンジン側に LLM を載せる手段として選択肢が少ない。
- 商用利用できる?
- 条件付きでできます。EUPL-1.2 は弱いコピーレフトのライセンスで、商用やクローズドソースのソフトウェアにも組み込めますが、このソフトウェア自体のファイルを改変して配布する場合は、その変更を同じライセンスで公開する必要があります。
- 今もメンテナンスされている?
- されています。直近 1 日以内に新しいコミットがあります。
- 何の言語で書かれている?
- 主に Rust です(GitHub の言語統計による)。
回答はプロジェクトの GitHub データ(最終同期:2026年9月15日)と当サイトの分析に基づくもので、法的助言ではありません。
オープンソース詳細解説
NobodyWho が埋めているのはバインディングの隙間であって推論カーネルではない
README は「Powered by the wonderful llama.cpp」と明記しており、推論の計算部分を独自実装しているわけではない。NobodyWho が提供するのは、GGUF 形式のモデルを読み込み、チャットのターン管理、ツール呼び出し用のグラマー生成、音声入出力をまとめて、Kotlin、Swift、Python、Flutter、React Native、Godot という 7 つの言語とフレームワークから同じ形で呼べるようにする層だ。llama.cpp 自体は C++ のライブラリで、モバイルやゲームエンジンから使うには FFI の橋渡しとビルド設定が要る。NobodyWho はそこを各プラットフォームのパッケージマネージャ経由で配布している。対象読者は、API キーを埋め込まずにアプリ内でチャットや音声処理を完結させたい開発者、とくに Godot や Flutter のように LLM 推論の選択肢が限られる環境の開発者だ。
モデル指定は hf:// と huggingface: の 2 系統に分かれる
各言語の Quick Start で使われているモデルパスは統一されていない。Kotlin、Swift、React Native は hf://NobodyWho/Qwen_Qwen3-0.6B-GGUF/Qwen_Qwen3-0.6B-Q4_K_M.gguf という形式で、Flutter と Python は huggingface:NobodyWho/Qwen_Qwen3-0.6B-GGUF/Qwen_Qwen3-0.6B-Q4_K_M.gguf という形式を取る。README にはこの違いの理由が書かれていない。同じモデルを指していることは名前から推測できるが、スキームの揺れはドキュメントを横断して読むときに混乱を招く。README の Features には「Hugging Face または任意の URL からモデルを直接読み込める」とあり、URL 指定も受け付ける。オフライン動作を売りにしている以上、初回のダウンロードをどう扱うかはアプリ側の設計判断になる。モデルファイルの配布経路を自前の CDN に置くなら URL 指定、Hugging Face に依存してよいならスキーム指定という使い分けになる。
ツール呼び出しは関数シグネチャからグラマーを生成する
Features の一文が NobodyWho の設計上の主張をよく表している。「automatically generates structured grammars from your function signatures, no schema writing needed」とあり、ツール呼び出し用の JSON スキーマを手で書く代わりに、ホスト言語の関数定義から GBNF などのグラマーを組み立てる。これは llama.cpp のグラマー制約付き生成を、各言語の型システムに接続する作業を省くものだ。Python なら型ヒント、Kotlin なら関数シグネチャが入力になる。ただし README にはどの程度の型まで対応するのか、ネストした構造体や Optional がどう扱われるのかの記述がない。実際に導入するなら、自分のツール定義を書いて生成結果を確認する作業が要る。型安全をうたっている分、対応範囲の外側に落ちたときの挙動を先に把握しておきたい。
コンテキストシフトでメッセージ長の上限を外す仕組み
Under the Hood に「Conversation-aware preemptive context shifting」とあり、会話の文脈を踏まえて事前にコンテキストをずらすことで、メッセージ長の制限なしに会話記憶を保つと説明されている。コンテキストウィンドウを超えた分を単純に切り捨てるのではなく、会話の流れを考慮して押し出す位置を決めるという主張だ。ただし README にはアルゴリズムの詳細も、押し出された情報がどれだけ失われるかの評価も載っていない。長い会話で古い指示が効かなくなる挙動は、この手の実装では避けにくい。制約のないメモリをうたう表現をそのまま受け取らず、自分のユースケースで長い対話を流し、どこで文脈が落ちるかを測る必要がある。GPU 加速は Vulkan か Metal 経由で、README は「any OS で高速に動く」と述べているが、具体的な数値は示されていない。
音声入出力はバックエンド名まで README に書かれている
Text-to-speech は Kokoro、Pocket TTS、Supertonic の 3 バックエンドが挙げられ、ローカルで WAV を合成する。Speech-to-text は Whisper を使う。マルチモーダル入力として画像と音声を LLM に渡せる。これらは別パッケージではなく同じ NobodyWho の中で扱われるため、音声付きのエージェントを 1 つの依存で組み立てられる。ただし README には各バックエンドのモデルサイズ、必要なメモリ、対応言語の記載がない。Kokoro と Whisper を同時にロードすればモデル 2 つ分のメモリを消費する。モバイルで動かすなら、チャット用モデルと音声モデルを同時に常駐させるのか、必要時にロードし直すのかを決める必要がある。この判断材料は README にはない。
導入はパッケージマネージャ経由で完結するが、Godot だけ手順が違う
Kotlin は build.gradle.kts に implementation("ai.nobodywho:nobodywho-android:2.0.0") を Android 向け、implementation("ai.nobodywho:nobodywho:2.0.0") をデスクトップ JVM 向けに追加する。Swift は SPM で https://github.com/nobodywho-ooo/nobodywho-swift.git を指定。React Native は npm install react-native-nobodywho、Expo は npx expo install react-native-nobodywho。Flutter は flutter pub add nobodywho。Python は pip install nobodywho。Godot だけはパッケージマネージャではなく、Godot 4.5 以降の AssetLib で NobodyWho を検索するか、GitHub のリリースページから zip を取得して AssetLib タブの Import で読み込む。README はこのとき ignore asset root オプションを設定するよう指示している。この手順を飛ばすとインポート構造が崩れる。7 つのプラットフォームのうち 6 つは 1 行のコマンドで済むが、Godot はエディタ内の操作が残る点で性質が異なる。
EUPL-1.2 はアプリへの組み込み方に影響する
ライセンスは EUPL-1.2 で、これは欧州連合が公開しているコピーレフト系のライセンスだ。MIT や Apache-2.0 のような寛容型と違い、改変物の配布時に同じライセンスの下でソースを提供する義務が生じる範囲がある。モバイルアプリに静的リンクして配布する場合、アプリ全体に伝播するかどうかはリンクの形態と解釈に依存する。ここで法的助言はできないので、自社の配布形態を弁護士に確認する以外にない。少なくとも、NobodyWho を組み込んだアプリをストアに出す前に、コピーレフトの条件を MIT 前提で見積もらないことだ。Rust のコア、各言語バインディング、Godot プラグインが同一リポジトリで同じライセンス下にある点も、依存の一部だけを切り出して扱いにくくしている。
代わりに検討すべきものと、向かないケース
サーバ側で完結させるなら vLLM が対照的な選択肢になる。vLLM は Python の推論サーバで、PagedAttention によるバッチ処理とスループット最適化を主目的に据え、複数クライアントからのリクエストを 1 つの GPU でさばく。NobodyWho は逆で、1 台の端末上の 1 アプリが自分のモデルを動かす前提だ。同時に何十ものリクエストを処理する設計ではなく、モデルの配布もアプリ側が抱える。したがって、ネットワーク越しに多数のユーザーへ LLM を提供する用途では NobodyWho は筋が悪い。また、対応する 7 プラットフォームの外側、たとえば組み込み Linux の C++ アプリに直接組み込むなら、llama.cpp を自分でリンクしたほうが依存が減る。NobodyWho の価値はバインディングにあるので、そのバインディングが不要な場所では価値も消える。
編集部の結論
採用を検討すべきなのは、モバイルアプリやゲーム内にチャット UI を組み込み、モデルの配布まで含めて自前で抱えたいチームだ。特に Godot 4.5 以降で AssetLib から導入できる点は、ゲームエンジン側に LLM を載せる手段として選択肢が少ない。逆に、サーバ側で GPU を占有できるなら vLLM のような推論サーバのほうが素直で、NobodyWho のバインディング層は不要な複雑さになる。導入前に確認すべきは、対象プラットフォーム向けのバインディングが実際にビルドできるか、そして EUPL-1.2 の伝播条件が自社の配布形態にどう掛かるかだ。まず Kotlin か Python のバインディングで Chat.fromPath に hf:// のモデルパスを渡し、ツール呼び出しの自動グラマー生成が自分の関数シグネチャで期待通りに動くかを確かめるのが最初の一歩になる。
コミュニティノート