技術仕様

このページは、現行 Android 実装をもとに、LLM tester with llama.cpp のフロントアプリ、設定保存、JNI ブリッジ、CMake/NDK ビルド、llama.cpp/ggml、API サーバー、WebUI 配信までの連携を技術仕様として整理したものです。

関連文書: 操作マニュアル | llama.cpp / JNI / CMake 深掘り | プライバシーポリシー

Android Activity UI Configuration JSON ModelManager JNI / C++ llama.cpp + ggml + mtmd Ollama / OpenAI 互換 API Bundled WebUI

目次

1. 全体像

このアプリは「UI から直接ネイティブ推論を叩く経路」と「端末内 HTTP サーバー経由で推論を叩く経路」の 2 本を持っています。どちらの経路でも、モデルロード・ビジー制御・パラメータ適用・再初期化は ModelManager に集約され、最終的な推論実体は llama_jni 共有ライブラリ内の llama.cpp / ggml / mtmd に到達します。

MainActivity / SettingsActivity
        ↓
ConfigurationManager / ModelFileHelper
        ↓
ModelManager
        ↓
LlamaNative (Java native wrapper)
        ↓ JNI
llama_jni (jni_llama.cpp)
        ↓
llama.cpp + ggml + mtmd + libcurl + mbedTLS

別経路:
OllamaForegroundService
        ↓
OllamaApiServer (HTTP, same-device / LAN)
        ↓
ModelManager → LlamaNative → JNI → llama.cpp
レイヤ主担当役割
UIMainActivity / SettingsActivity / DocumentsActivity入力、状態表示、ログ表示、設定編集、API/WebUI 起動停止
設定ConfigurationManagerプロファイル JSON の保存・読込、既定値提供
モデル資産ModelFileHelperGGUF / mmproj のファイル名解決、保存場所、モダリティ推定
実行制御ModelManagerロード、再初期化、排他制御、ネイティブ呼び出し集約
Java ↔ NativeLlamaNativenative メソッド公開、トークン進捗コールバック登録
Native 実装jni_llama.cppグローバル状態、初期化、サンプリング、停止シーケンス、ログ、クラッシュ記録
HTTPOllamaApiServer / OllamaForegroundServiceOllama 互換 API、OpenAI 互換 API、WebUI 静的配信、待機キュー

2. フロントアプリ層

2-1. MainActivity の役割

2-2. SettingsActivity の役割

2-3. 起動時 / バックグラウンド連携

3. 設定・モデルファイル管理

3-1. ConfigurationManager

各プロファイルは外部ファイル領域の configs/*.json として保存されます。既定プロファイルは初回起動時に自動生成され、モデル URL、生成パラメータ、Think、GPU Offload、カスタムテンプレート、system prompt、mmproj 参照などを保持します。

カテゴリ主な項目用途
モデルmodelUrl, multimodalProjectorUrlGGUF と任意の mmproj 参照
ロード系nCtx, nThreads, nBatch, gpuOffloadLayersコンテキスト、CPU、GPU オフロード設定
サンプリングtemp, topP, topK, Penalty, Mirostat, DRY, XTCサンプラー構築にそのまま反映
テンプレートsystemPrompt, customChatTemplate, enableThinkingプロンプト生成の最終形を制御
UI / 挙動streaming画面・API のストリーミング出力既定値

3-2. ModelFileHelper

3-3. 分割 GGUF と HTTPS ダウンロード

4. ModelManager の責務

ModelManager は UI と HTTP サーバーの共通実行基盤です。排他制御、モデルロード、再ロード、パラメータ適用、ネイティブログ設定、ダウンロード前の trust store 準備まで集約しています。

4-1. 排他と再初期化

4-2. ロード手順

  1. プロファイルを読み込む。
  2. モデルファイル名を決定し、保存先パスを作る。
  3. 必要なら mmproj を自動検出またはダウンロードする。
  4. モデルファイルが無ければ Native download を実行する。
  5. 同一モデル再利用でなければ既存 model/context/mmproj を解放する。
  6. PRELOAD: n_ctx=64 で一度 initWithMmproj() を呼び、ロード可否を早めに判定する。
  7. 本初期化: 本来の n_ctx に戻して再度 initWithMmproj() を呼ぶ。
  8. applyConfiguration() でサンプリング系パラメータを Native 側へ反映する。

この 2 段ロードにより、巨大コンテキストでいきなり失敗する前に、最小限コンテキストでモデルファイル自体のロードを先に確認する構成になっています。

4-3. 推論時の扱い

5. JNI / C++ 層

5-1. Java 側の公開 API

LlamaNativeSystem.loadLibrary("llama_jni") で共有ライブラリをロードし、以下を公開します。

メソッド用途
download(url, path)libcurl によるモデル / mmproj ダウンロード
initWithMmproj(modelPath, mmprojPath)モデルと任意の multimodal projector 初期化
setLoadParameters(...)ロード前に必要な n_ctx / n_threads / n_batch / GPU 層数を設定
setParameters(...)Penalty / DRY / Mirostat / XTC などサンプラー関連を設定
generate(prompt), generateWithMedia(prompt, media)テキスト / マルチモーダル生成
setTokenListener(listener)ストリーミングトークン、完了、エラーのコールバック登録
cancelGeneration()ネイティブ生成ループへ停止要求
getChatTemplate()GGUF メタデータから chat template を取り出す
supportsVision(), supportsAudio()現在ロード済みモデルのモダリティを返す

5-2. Native 側のグローバル状態

5-3. initWithMmproj の流れ

  1. fatal signal handler を一度だけインストールし、ネイティブクラッシュ時に native_crash.txt へ痕跡を残せるようにします。
  2. llama.cpp と mtmd のログコールバックを登録します。
  3. モデルファイル、mmproj ファイル、split GGUF の欠落を検査します。
  4. 既存 model / context / mtmd を必要に応じて解放します。
  5. llama_backend_init() を呼び、登録済み ggml backend 数を確認します。
  6. llama_model_default_params()n_gpu_layers を反映して llama_model_load_from_file() を実行します。
  7. llama_context_default_params()n_ctx, n_threads, n_batch, n_threads_batch を入れて llama_init_from_model() を実行します。
  8. 必要なら initialize_optional_multimodal_support_locked() で mtmd を初期化し、vision/audio サポートを確定します。

5-4. generate の流れ

  1. 現在の memory をクリアし、prompt prefill に備えます。
  2. テキストのみなら prefill_text_prompt_locked()、画像 / 音声付きなら prefill_multimodal_prompt_locked() を使います。
  3. prefill 成功後に sampler chain を構築します。
  4. 最大 1024 トークンまでループし、毎ステップ llama_sampler_sample()llama_sampler_accept()llama_decode() を実行します。
  5. stop sequence 検出、EOG、context safety limit、cancel flag のいずれかで終了します。
  6. 差分トークンは notify_token_delta() で Java へ渡し、完了時は notify_token_complete() を送ります。

5-5. サンプラー構成

Native 側は Java の設定値を直接 sampler chain に変換します。順序は概ね以下です。

penalties
→ DRY
→ top_n_sigma
→ top_k
→ typical
→ top_p
→ min_p
→ XTC
→ temperature / dynamic temperature
→ mirostat v1 or v2 / fallback dist

DRY の sequence breakers は Java の既定値 \n,:,",* と同期されており、JNI 側でエスケープ展開して llama_sampler_init_dry() に渡されます。

5-6. 停止条件と出力整形

5-7. ダウンロード・ログ・クラッシュ

6. CMake / NDK ビルド

一般的な llama.cpp 導入の観点から JNI 境界や CMake 構成をさらに詳しく見る場合は、llama.cpp / JNI / CMake 深掘り を参照してください。

6-1. Gradle / NDK 側の特徴

6-2. CMake 側の構成

6-3. Android 向けリンク上の注意

6-4. この構成の意味

つまりこのアプリは「Java から JNI で共有ライブラリを呼ぶ」だけでなく、llama.cpp / ggml / mtmd / curl / TLS を Android 向けに一体ビルドした専用ランタイムを APK 内に持つ設計です。フロントアプリのボタン操作は、そのまま自前ビルドのローカル推論エンジンを制御する操作になっています。

7. API サーバー仕様

OllamaApiServer は軽量な独自 HTTP サーバーです。Foreground Service の中で待受し、同じ port 上で API と WebUI を同居させます。既定ポートは 11434 です。

7-1. 提供エンドポイント

経路主用途備考
POST /api/generate単一 prompt 生成Ollama 風 NDJSON streaming / 非 streaming 両対応
POST /api/chatmessages 配列による会話生成モデル family に応じて multi-turn prompt 化
GET/POST /api/tagsモデル一覧プロファイル一覧をモデル名として返す
POST /v1/chat/completionsOpenAI 互換 chat completionsSSE streaming 対応
GET /v1/models, /modelsモデル一覧 + 状態loaded/unloaded, modalities, path などを返す
GET /propsllama.cpp WebUI 向け model propsdefault_generation_settings, chat_template, webui_settings
GET /slotsslot 情報総 slot 数は 1 固定
GET /health, /v1/healthヘルスチェックrolewebui=true を返す
/, /index.html ほかBundled WebUI 配信asset cache 付き

7-2. 同時実行と待機キュー

7-3. /api/generate と /api/chat の内部処理

  1. リクエスト JSON を読む。
  2. acquireGenerationSlot() で排他を取る。
  3. 要求モデル名に対応する configuration をロードする。
  4. GGUF chat_template、custom template、system prompt、Think 設定を使って最終 prompt を組み立てる。
  5. request の tools か共有ツール設定がある場合は SharedToolManager.generateWithTools() に切り替わり、最大 10 ターンまで自動ツール実行を継続できます。
  6. streaming 時は token queue + writer thread を立て、ネイティブ生成スレッドをネットワーク I/O で止めない。
  7. client disconnect や end marker 検出時は cancelGeneration() を発行する。

7-4. マルチモーダル入力の扱い

7-5. OpenAI 互換層の特徴

8. WebUI と配信方式

8-1. WebUI の正体

8-2. WebUI と API の結合

8-3. 運用上の意味

つまり Android アプリは「ネイティブ推論エンジン + Ollama/OpenAI 互換 API + その API を使う WebUI」を 1 台の端末上に同梱した構成です。ローカルブラウザや LAN 内クライアントから同じ端末へアクセスするだけで、外部サーバーを置かずに一式を試せます。

9. 公開 Web ページとの関係