Jev Local

September 19, 2026 · View on GitHub

文章・JSON・画像に対する質問を、Choice(選択肢)・Score(段階評価)・Noul(真偽)の確率として返すローカルAPIです。同じ/v1/systemoneを、性質の違う2つのバックエンドで提供します。

LFM(既定)ModernBERT
モデルLFM2.5-1.2B Instruct / LFM2.5-VL-1.6B(llama.cpp, Q8_0)ModernBERT-Ja 310Mをcross-encoderとしてfine-tune
判定方式回答先頭トークンのlogprob(zero-shot)(質問+State, 候補)ペアの採点(学習済み重みを配布)
入力文章・JSON・画像文章・JSON
強いところ知識・未知の分類体系・自由な指示文日本語の意図・関係判定と速度。候補順に依存しない
追加依存なし(バイナリを自動取得)torch+transformers(別venv)
JGLUE testJNLI 17% / JComQA 69%JNLI 93% / JComQA 92%(trainで学習)

クライアント・評価ツール・API仕橘は共通です。まずLFMで動かしてから、必要に応じてModernBERTバックエンドを追加する想定です。

Jev本体のモデル・学習・精度を再現するものではありません。 TypeSafeの/v1/systemone形式に合わせた非公式アダプターです。画像入力はローカル拡張で、公式SDKの画像互換を意味しません。APIの互換範囲を参照してください。

セットアップと起動(LFM)

Python 3.12以上とBashが必要です。自動セットアップはLinux x86_64・arm64、macOS(Apple Silicon・Intel)に対応し、WindowsではWSL2を使用します。通常実行に追加Pythonパッケージやコンパイルは不要です。

git clone https://github.com/Argos1111/jev_local.git
cd jev_local
./setup.sh --model text
./run.sh --model text

画像も入力する場合は、次の構成を選びます。

./setup.sh --model vision
./run.sh --model vision

textは文章用モデルだけ、visionはVLモデルと画像エンコーダーを取得します。選択は保存され、以後の./run.shはそのモデルを使います。両方を取得済みなら、./run.sh --model text--model visionだけで切り替えられます。切り替える際は稼働中のサーバーをCtrl+Cで停止してから起動してください。未設定時の既定はtextです。

setup.shはGPUを検出してCUDA・ROCm・Metal版のllama.cppを選択し、選択したモデルを取得・SHA256検証します。VL構成は画像エンコーダー(mmproj F16)込みで約2.1 GBです。GPUを利用できない場合は理由を表示してCPU版に切り替えます。初回のみGitHub・Hugging Faceへのネット接続が必要です。

GPUドライバーやROCmの共有ライブラリは別途必要です。OSのパッケージは自動インストールしません。CPUに固定する場合は./setup.sh --backend cpuを使います。対応環境・手動設定・トラブルシューティングを参照してください。

Ready: http://127.0.0.1:8080が表示されたら、サーバーを動かしたまま別ターミナルから入力を送ります。 Ctrl+Cで推論サーバーとAPIの両方が停止します。Connection refusedの場合は起動状態と送信先ポートを確認してください。

ランタイムを変更せずモデルだけ追加する場合は./setup.sh --model vision --model-only(文章用は--model text)を使います。LFM_MODELLFM_MMPROJを設定済みの場合はそれらが優先されるため、標準モデルの選択を使う前にunset LFM_MODEL LFM_MMPROJで解除してください。

テキスト・JSONで試す

python3 systemone_client.py
python3 systemone_client.py --input examples/systemone.json --format json
python3 systemone_client.py --input examples/systemone.json --output results/my_result.json

既定のサンプルは顧客の問い合わせに対する12問です。--format jsonで生JSONを表示します。--outputの保存内容は表示形式にかかわらずJSONです。自分の入力にはexamples/systemone.jsonstatequestionsを書き換えてください。

画像で試す

./run.sh --model visionで起動します。画像を自分で用意し、ローカルの画像フォルダなどに置きます。画像はリポジトリに同梱していません。

python3 systemone_client.py \
  --input examples/vision.json \
  --image sample_pics/photo.jpg

GSS資料向けの12問4問もあります。対応する画像を用意した場合は次のように実行できます。

python3 systemone_client.py \
  --input examples/vision_gss_4.json \
  --image sample_pics/20260911_image_resized.png \
  --format json \
  --output results/my_vision_gss_4.json
``$

**速度を優先する場合は、画像の縦横をともに512\text{px}以内に収め(縦横比を維持)、質問を4問に絞る構成を推奨します。** 今回の検証では、512 \times 286\text{px}・4問・\text{GPU}・画像エンコード再利用の組み合わせが最も速く、同じ画像の再送は中央値約98\text{ms}でした。4問は4並列の1回分に収まります。画像サイズや質問数を網羅的に比較した結果ではなく、1〜3問より4問が速いことを意味しません。縮小と質問の選定は入力前に行います(自動変換・4問制限はありません)。

- \text{PNG}/\text{JPEG}、1枚4 \text{MiB}、最大4枚。複数枚は$--image`を繰り返します。
- HTTPではトップレベルの`images`配列にbase64 data URLを渡します。[画像API仕様](docs/API.md#画像入力ローカル拡張)を参照してください。
- 大きな画像・複数画像には`CTX_SIZE=32768 ./run.sh --model vision`などでコンテキストを増やします。既定は4 slots・合計8192トークンです。
- 各質問は独立に推論し、最大4問を並列処理します。画像入力ではdecoder側の共通Stateキャッシュを使いません。

## 画像エンコードの再利用(実験機能)

同じ画像を複数質問に使う場合、画像エンコーダーの出力だけをメモリ内で再利用するオプションがあります。**Linux x86_64 / AMD ROCm向けの追加ビルド**が必要です。通常の`setup.sh``run.sh`だけでは有効になりません。[ビルドと起動手順](docs/IMAGE_CACHE.md)に従って準備してください。

```bash
# ビルド済みの場合。通常サーバーとは別ポートを使用する例
./run_image_cache_gpu.sh --port 18080 --backend-port 18097

このサーバーに送るクライアントでは--url http://127.0.0.1:18080を追加します。画像+stateを読み込むdecoderの処理と各質問の判定は、引き続き質問ごとに実行します。

Radeon AI PRO R9700・512×286 px画像・4問での測定例:

条件応答時間
再利用なし、10回の中央値358 ms
初回の画像、1回計算+3回再利用(2回測定)192〜212 ms
同じ画像を再送、10回の中央値98 ms

モデルロードを除くHTTP応答時間です。1画像での実験値で、速度や正答率を保証するものではありません。測定条件と精度上の制約も参照してください。

ModernBERTバックエンド(文章のみ)

LLMの先頭トークン判定ではなく、sbintuitions/modernbert-ja-310mを「(質問+State, 候補)ペアの採点器」としてfine-tuneし、同じAPIを提供する構成です。torch+transformersを別のvenvに導入します。候補順への依存がなく、1リクエストの全質問を1回のバッチ推論で処理します。

./setup_modernbert.sh        # .venv-modernbert(torch/transformers)。GPUを自動検出
./run_modernbert.sh          # 学習済み重み argos1111/modernbert-ja-310m-jev を取得して起動(初回約1.3 GB)
python3 systemone_client.py  # クライアントは共通

学習済み重みはHugging Face Hubで公開しています(CC BY-SA 4.0)。推論はVRAM約2 GB、CPUでも動作します(12問で約2秒)。

自分で学習する場合は./train_modernbert.shを実行します。公開日本語データ(JGLUE train・JCoLA・JCommonsenseMorality・MASSIVE)を自動取得し、R9700で約40分、bf16でVRAM約20 GB(--pair-budget 64で約10 GB)です。models/modernbert-ja-310m-jev/ができると./run_modernbert.shはそちらを優先します。

画像入力は非対応で、imagesを含むリクエストは422を返します。JGLUEの高い数値は同じデータのtrainで学習した結果です。学習に使っていないタスクでは特性が分かれます:知識を問うタスク(ニュース分類・JMMLU)はLFMの方が高く、短い日本語の意図判定(顧客対応の手作り16例)はModernBERTの方が高い結果でした。数値と条件、学習データとライセンス、OS別の対応状況はModernBERTバックエンドを参照してください。

API

curl http://127.0.0.1:8080/v1/systemone \
  -H 'Authorization: Bearer local-dev' \
  -H 'Content-Type: application/json' \
  --data-binary @examples/systemone.json
質問のtype得られるもの
choice選んだ候補、候補ごとの確率、分布の集中度
score段階番号の期待値、各段階の確率、分布の集中度
noul真である確率(0〜1)

確率は指定した候補の中で正規化した値です。confidenceは分布の集中度で、正解率として校正された値ではありません。仕組みと制約を参照してください。

フォルダ構成

api_server.py / systemone.py       HTTP APIと型付き判断
jev_local.py / state_cache.py      候補確率の計算・テキストStateの再利用
image_input.py                    画像の検証・data URLへの変換
systemone_client.py / display.py   クライアント・結果表示
modernbert/                       ModernBERT cross-encoderの学習・推論・API
scripts/                          セットアップ・起動・実験ビルド
native/                           画像エンコードキャッシュとC++単体テスト
examples/                         リクエストJSON
sample_pics/                      ローカル入力画像(画像はGit対象外)
tests/                            Python単体テスト
tools/                            動作確認・評価・速度測定
docs/                             詳細な設定・仕様・測定条件
models/ .cache/ results/ .venv*/   ローカル生成物(Git対象外)

モデル・画像・生ログ・計測結果・ビルド成果物はGitHubに含めません。公開する測定要約はdocs/にまとめています。results/内のファイルを編集しても配布コードにはならないため、再利用するスクリプトはtools/で管理します。

開発・検証

python3 -m unittest discover -s tests -v  # モデル・ダウンロード不要
python3 -m tools.verify_api              # 起動済みAPIの実通信確認
python3 -m tools.verify_vision           # 合成画像で画像入力を確認
python3 -m tools.benchmark_jglue --output results/jglue      # JGLUE test(どちらのバックエンドでも)
python3 -m tools.evaluate_heldout_tasks --output results/ho  # 学習に使っていないタスクでの比較

CIではPythonテスト・シェル構文と、モデル不要のC++キャッシュテストを実行します。ModernBERTのテストも疑似エンコーダーで動くため、CIにtorchは不要です。GPU推論の確認はローカルで行います。

依存するllama.cppLFM2.5モデルModernBERT-Ja(MIT)は、それぞれの配布元の利用条件に従います。ModernBERTの学習に使う公開データセット(JGLUE・JCoLA・JMMLU: CC BY-SA 4.0、JCommonsenseMorality: MIT、MASSIVE: CC BY 4.0、livedoor: CC BY-ND 2.1 JP)は実行時に取得し、リポジトリには含めません。学習済みモデルを再配布する場合はCC BY-SAの継承条件に留意してください。本プロジェクトにバイナリ・モデル重みは同梱しません。