OpenClaw の Local LLM 設定と Vision モデルの変更方法

OpenClaw とは

OpenClaw はクラウドサービスではなく、自分の PC 上で走らせることができる AI エージェントです。インターフェースとして各種メッセージングツールを利用しているので、Slack や Discord、iMessage や LINE など、普段使い慣れているアプリでそのまま AI と対話することができます。PC でもスマートフォンでも、普段使ってるアプリがそのまま AI エージェントの窓口になるわけです。

OpenClaw のエージェントが従来の AI と異なっている点は、最初から直接 PC を操作できることです。例えばネット検索で情報集めを依頼した場合、正しい手順を踏む場合は Brave Search や Perplexity 検索サービス等の API Key が必要となります。

ところが OpenClaw のエージェントでは、これらのサービスが使えない場合でも代わりの方法を探し出そうとします。curl 系のコマンドで直接ページの取得を試みたり、Chrome ブラウザを起動して Google 検索を利用したりと、自分で解決策を求めて試行錯誤を行い目的を完遂しようとします。この動きは自動的に行われているので、依頼した人間は裏でどんな方法が使われていたのかを知る必要がありません。面倒なことは AI に任せて結果だけを受け取ればいいのです。

柔軟性が高く応用力に富む反面、当然ながら知らないうちに意図しない操作が行われてしまうリスクもあります。OpenClaw を使う場合は仮想マシンのような隔離したサンドボックス環境を使い、普段自分が使っている重要な情報満載の PC にはそのままインストールしないようにしてください。

OpenClaw のインストール方法などの手順は以下の Wiki の方にまとめています。逐次更新していますのでこちらも参照してください。

今回は OpenClaw で Local LLM を設定するための設定などを解説していきます。(Local LLM は自分の PC 上で走らせられる LLM のことです。Local LLM について詳しくはこちら)

OpenClaw インストーラーの Model の選択をスキップする方法

OpenClaw が使用する LLM (大規模言語モデル) は、インストール時に任意のサービスを選択することができます。Claude や OpenAI、Gemini など豊富なクラウド LLM の API を選択することが可能ですが、この選択肢には Local LLM 用のプロバイダが含まれていません。そのため Local LLM を使いたい場合はこの画面はとりあえず無難なものを選んでスキップし、あとから設定ファイルを書き換える必要があります。

スキップするためのおすすめの選択肢は以下の通りです。モデルの Provider 選択肢から

「Skip for now」→「openai」→「Keep current」

初回のインストーラーでモデル選択をスキップした場合でも、あとからモデルの選択だけやり直すことが可能なので安心してください。やり直す場合はコマンドラインから以下のように実行します。

openclaw configure --section model

もし openclaw コマンドが見つからないと言われた場合はまだパスが通っていないので、最初に「. ~/.bashrc」を実行してから上のコマンドを実行してください。「~」の文字が入力できない場合は「$HOME」に置き換えてください。

.  ~/.bashrc
openclaw configure --section model

OpenClaw の設定ファイルを書き換える方法

OpenClaw の設定ファイルは ~/.openclaw/openclaw.json にあります。使用する LLM の設定もこのファイルに記述することができます。

Local LLM 向けに設定を書き換える場合のポイントは以下の 2 点です。

  1. プロバイダを新規追加する場合は “ollama” のような既存の名前と重なるものを避けて “ollamalocalpc” のように別名にする。
  2. 書き換えたあとは必ず「 openclaw gateway restart 」を実行して Gateway (OpenClaw サーバー) を再起動する。

1. インストール時の選択肢には出てこないものの、OpenClaw には Ollama 向けのプロバイダがプリセットとして定義されています。このプリセットは localhost を見に行くので、baseUrl で IP ドレスを書き換えても反映されないことがあります。完全に新規の別名で追加した方が確実です。

2. openclaw status などのコマンドでは直接 openclaw.json を読み取っていますが、これが必ずしも Gateway に反映されているとは限らないようです。表示されているモデルと実際に使われているものが異なる場合があるので、openclaw.json を変更したら必ず「 openclaw gateway restart 」を実行するようにしてください。

以下は、別の PC 上で動いている LMStudio を使用する場合の設定例です。openclaw.json には他の設定も含まれているので、以下の “models” の項目を追加してください。(openclaw.json の前後の部分は省略しています)

Local LLM プロバイダとモデルの定義

  "models": {
    "providers": {
      "lmstudiolocalpc": {
        "baseUrl": "http://<PC-IP-ADDRESS>:1234/v1",
        "apiKey": "lmstudio",
        "api": "openai-completions",
        "models": [
          {
            "id": "openai/gpt-oss-120b",
            "name": "openai/gpt-oss-120b",
            "reasoning": true,
            "input": [
              "text"
            ],
            "cost": {
              "input": 0,
              "output": 0,
              "cacheRead": 0,
              "cacheWrite": 0
            },
            "contextWindow": 65536,
            "maxTokens": 32768
          }
        ]
      }
    }
  },

<PC-IP-ADDRESS> の部分は LMStudio が動いている PC のアドレスに置き換えます。OpenClaw と LMStudio が同じPC 上で動いている場合は 127.0.0.1 で構いません。

モデルの指定

このモデルを実際に使用する場合は agents.defaults.model.primary に指定します。

  "agents": {
    "defaults": {
    
    
      "model": {
        "primary": "lmstudiolocalpc/openai/gpt-oss-120b"
      },
      
      
      "workspace": "/home/<USERNAME>/.openclaw/workspace",
      "compaction": {
        "mode": "safeguard"
      },
      "timeoutSeconds": 1800,
      "maxConcurrent": 4,
      "subagents": {
        "maxConcurrent": 8
      }
    }
  },

<USERNAME> の部分は自分のユーザー名が最初から入っているはずです。

Ollama を使う場合も同じように設定できます。以下のページ Ollama を含めたさまざまな設定例を置いてあるのでこちらも参照してください。

画像認識用モデルの設定

OpenClaw は画像の認識を行うことができます。Slack や Discord へ投稿した画像はもちろんですが、ローカル PC 上に保存したファイルの認識もしてくれます。この場合は LLM (VLM) を使った認識が行われます。

Claude や GPT-5, Gemini 3 などの商用の推奨モデルは最初からマルチモーダルなので画像の認識が可能です。ですが Local LLM を使用する場合は対応していないことが多いので、OpenClaw では画像識別用に別途 VLM を設定する機能があります。

以下のように、agents.defaults.model.primary とは別に画像認識用の VLM を agents.defaults.imageModel.primary に設定します。以下の例では「 qwen3-vl-8b 」を設定しています。

  "agents": {
    "defaults": {
 
      "model": {
        "primary": "lmstudiolocalpc/openai/gpt-oss-120b"
      },

 
      "imageModel": {
        "primary": "lmstudiolocalpc/qwen/qwen3-vl-8b"
      },


      "workspace": "/home/<USERNAME>/.openclaw/workspace",
      "compaction": {
        "mode": "safeguard"
      },
      "timeoutSeconds": 1800,
      "maxConcurrent": 4,
      "subagents": {
        "maxConcurrent": 8
      }
    }
  },

qwen3-vl-8b を含めたプロバイダ側のモデルの定義は以下のとおりです。qwen3-vl-8b 側の input の項目 ( models.providers.lmstudiolocalpc.models[1].input ) に “image” を追加しており、これで画像を受け取れるようにします。

  "models": {
    "providers": {
      "lmstudiolocalpc": {
        "baseUrl": "http://<PC-IP-ADDRESS>:1234/v1",
        "apiKey": "lmstudio",
        "api": "openai-completions",
        "models": [
          {
            "id": "openai/gpt-oss-120b",
            "name": "openai/gpt-oss-120b",
            "reasoning": true,
            "input": [
              "text"
            ],
            "cost": {
              "input": 0,
              "output": 0,
              "cacheRead": 0,
              "cacheWrite": 0
            },
            "contextWindow": 65536,
            "maxTokens": 32768
          },
          {
            "id": "qwen/qwen3-vl-8b",
            "name": "qwen/qwen3-vl-8b",
            "reasoning": true,
            "input": [
              "text",
              "image"
            ],
            "cost": {
              "input": 0,
              "output": 0,
              "cacheRead": 0,
              "cacheWrite": 0
            },
            "contextWindow": 32768,
            "maxTokens": 32768
          }
        ]
      }
    }
  },

これで画像認識非対応の Local LLM 利用時でも画像の識別ができるようになります。また GLM-5 などのクラウドモデルで Vision に対応していない場合にも、画像認識を Local LLM で補うことができるようになります。

商用 API などの既存のモデルが image 入力に対応しているかどうかは、以下のコマンドで確認することができます。

openclaw models list --all

OpenClaw で Local LLM を使う場合の注意点

OpenClaw のエージェントは自律的な動作を行うのでさまざまなリスクがあります。例えばネットから得た情報には悪意を持ったプロンプトが含まれている可能性があります。偽の指示に騙されないようにするためには、ある程度パラメータ数の多い LLM が必要です。

OpenClaw ではサンドボックスなしにネットアクセスを許可する場合 300b 以上のモデルを推奨しているようで、パラメータ数が少ないモデルの場合は openclaw status 等のコマンド実行時に警告が表示されます。OpenClaw のインストーラーに Local LLM の選択肢が含まれていないのも、このあたりの事情によるものではないかと思われます。

そのため今回の説明では gpt-oss 120b を例に上げていますが、実際に使う場合はもっとパラメータ数が多いモデルを使うことをお勧めします。パラメータ数が少ない Local LLM をエージェントとして使ってみると、なかなか思い通りに動かなかったりと割と暴走しがちです。より上位モデルを使うと安定したりします。

もちろんサンドボックスなどクローズドな環境で動作テストに使う場合は利用できますので、テスト時のトークン数節約目的とか、いろいろと応用できるのではないかと思います。

Android 16 の Pixel 付属の機能で GPU 対応の Linux Desktop を使う

Google Pixel シリーズ用 Android 16 には試験機能として Linux のコマンドライン開発環境が入っています。2025年 12月の更新で Linux の GUI アプリケーションも実行できるようになっていたので試してみました。機種依存ですが GPU によるハードウェアアクセラレーションにも対応しているようです。

Android Developers Blog: Android 16 QPR2 is Released

↓ Pixel 10 Pro 上で Firefox, gimp, vscode を起動してみたところ。外部ディスプレイではなく Pixel の実機画面です。

Pixel 10 Pro 上で Firefox, gimp, vscode を起動してみたところ

↓ Pixel 10 Pro は GPU アクセラレーションに対応

Pixel 9a にはこの設定が無く、ソフトウエアレンダラが使われているようです。Linux の GUI アプリケーション自体は 9a でも実行できます。

Linux ターミナルのインストール

  1. 画面自動消灯の時間を 30分に変更
    • 設定 → ディスプレイとタップ → 画面自動消灯 → 30分を選択
    • ※ インストールが完了したら元の時間に戻しておいてください
  2. 開発者向けオプションを有効化
    • 設定 → デバイス情報 → ビルド番号 の欄を 7回タップ
  3. 開発者向けオプションから Linux ターミナルを有効化
    • 設定 → システム → 開発者向けオプション → Linux開発者環境 (試験運用版) を有効化
    • これで Pixel に「ターミナル」アプリが追加されます
  4. Linux のインストール
    • 「ターミナル」アプリを起動して「インストール」をタッチ
    • ホーム画面には自動的に追加されないので、アプリケーションドロワーから「ターミナル」のアイコンを探してください
  5. ターミナルが起動したら以下のコマンドを実行
sudo apt update
sudo apt upgrade -y
sudo apt install fonts-noto-cjk

これで Linux ターミナルが使えるようになります。GUI アプリケーションも利用可能です。

また以前のバージョンとは異なり、Linux 向けストレージの容量制限がなくなっていました。そのため設定からストレージサイズをいちいち拡張する必要はなく、そのまま利用することができます。

※ 画面の自動消灯時間を元に戻しておくのを忘れないようにしてください。

GUI アプリケーションの利用

ターミナルアプリの右上 (赤枠部分) に GUI アプリケーション用のボタンがあります。

最初は真っ黒で何も表示されていませんが、GUI アプリケーションを起動するとこのエリアに表示されます。CLI ターミナルとは別物で、ソフトキーボードの仕様も違います。Adnroid の「戻る」操作でターミナルに戻ります。

右端にマウスらしきアイコンがありますが、ソフトウエアマウスではないので注意。これは外部接続した Bluetooth / USB マウスを Linux 側でキャプチャするかどうかの切り替えです。

デフォルトでは Android 側のマウスカーソル(↓下の画像)が表示されます。この場合左ボタンしか反応せず、カーソルも Linux 画面外に移動可能で Android の操作ができます。

マウス切り替えのボタンをタッチすると Linux VM のマウスカーソル(↓下の画像)の直接操作になり、右ボタン、中ボタンが使えるようになります。カーソル移動範囲も Linux GUI 画面内に制限されます。GUI アプリケーションの操作時はこちらに切り替えておくことをお勧めします。

横全画面に切り替えた場合はソフトウエアキーボードが使えないので、Bluetooth / USB のキーボードやマウスが必要です。Android の「戻る」操作で元の画面に戻ります。

Linux 版 firefox を使ってみる例

ターミナル側で以下のコマンドを実行します。

sudo apt install firefox-esr -y
firefox-esr

これだけでは何も表示されないので右上のアイコンから GUI アプリケーション画面を開きます。以下のように起動できていることがわかります。

画面タッチでも使えますがマウスがないと細かい操作ができません。GUI 画面上で Firefox のウィンドウを閉じられない場合は、ターミナル側から Ctrl + C で止めてください。

Linux Desktop を試す

例にあげた firefox のように、そのまま起動すると全画面になります。複数のアプリケーションを実行できるように設定を変えてみます。

(1) /etc/systemd/user/weston.service を編集

「ExecStart=」の行があるので、--shell= 以降行末までを desktop に置き換えます。

ExecStart=/usr/bin/weston --modules=systemd-notify.so --xwayland --shell=kiosk-shell.so --continue-without-input

↓以下のように変更

ExecStart=/usr/bin/weston --modules=systemd-notify.so --xwayland --shell=desktop

(2) ~/.config/weston.ini を以下の内容で作成

[shell]
locking=false
panel-position=bottom
panel-height=32
fullscreen=false

panel の位置を下に移動したのは、一部のアプリケーションでタイトルバーに重なってウィンドウ操作ができなくなるためです。

(3) 一旦ターミナルアプリを終了します

すべてのターミナルで exit を実行して Linux ターミナルアプリを閉じます。Android の通知領域に以下のように「ターミナルを閉じています」と表示されている場合は、この通知が消えるまで待ってください。

(4) ターミナルアプリを再起動します

通知が消えて完全に終了したことを確認したら、再びターミナルを起動して GPU アプリケーション画面を開きます。しばらくすると weston のシンプルな Linux デスクトップ画面が表示されています。

  • 最初画面が真っ暗で何も表示されていない場合はしばらく待ってみてください。
  • それでも表示されない場合は画面のタッチ、外部接続マウスの操作やマウス切り替えボタンのタッチ、横全画面に切り替えてから「戻る」などの操作を行ってみてください。一定時間操作が無いために画面が暗転していることがあります。

画面が表示されたら、以下のようにタスクバー左端のアイコンから GUI 版ターミナルを開くことができます。

これで Linux の GUI アプリケーションをウィンドウモードで起動することができるようになります。

気がついたことなど

「GPU アクセラレーテッド レンダラ」の場合、アプリケーションによっては表示が崩れることがあります。Firefox など。「ソフトウエアレンダラ」に切り替えると安定します。

ソフトウエアレンダラの場合は Linux 側のマウスカーソルの追従が悪くなるようです。少々操作しづらいですが、ウィンドウの移動や範囲のドラッグなどマウス左ボタン押しながらの操作はスムーズなので描画が遅いわけではないようです。

ストレージ容量の制限はなくなりましたが、Linux VM 側で利用可能な RAM は以前と変わらず 4GB のままのようです。Pixel 10 Pro (RAM 16GB) でも Pixel 9a (RAM 8GB) でも同じ 4GB でした。

GUI アプリケーション側のソフトキーボードは、ターミナル側と操作方法が若干違います。Ctrl などの修飾キーがロックされずに同時押しです。

以下は Pixel 9a で firefox, gimp, vscode, blender を起動してみたところです。(ソフトウエアレンダラ)

Pixel 9a で firefox, gimp, vscode, blender を起動してみたところ

まだ不安定な部分もありますが、今後いろいろと改良されていくものと思われます。使用できるアプリケーションも増えますし、Pixel スマートフォン単体だけで PC のように使えるのは魅力的です。

UE5 5.5 複数 PC 環境でクックを速くする Zen Storage Server の Shared DDC をできるだけ簡単にセットアップする

Unreal Engine のクックには時間がかかります。特に初めて新しいバージョンの Editor を起動する場合はシェーダーコンパイルに時間がかかり、スプラッシュ画面のまましばらく待つことになります。

複数台 PC を持っている場合はそれぞれの PC 毎に同じビルドが走るのですが、Shared DDC を使うとこの起動待ち時間を大幅に短縮することができます。

UE5 5.5 からは共有フォルダを使わずに Zen Storage Server を使った Shared DDC が使えるようになりました。直接ファイルシステムを使うよりも効率が良く高速化されています。

普段使ってる PC でも Shared DDC が使えるように、できるだけ簡単な手順で Zen Server をセットアップしてみます。

公式のドキュメントはこちらです

UNREAL ENGINE : Zenserver as Shared DDC

セットアップ手順

OS は Windows 11 Home / Pro どちらでも構いません。以下の手順は Home を元に解説しています。

(1) インストールするフォルダの準備

今回は仮に C:\zen 以下に作成するものとして説明します。パスは必要に応じて置き換えてください。C:\zen 以下に ZenInstall と ZenData フォルダを作成します。

C:\zen\ZenInstall
C:\zen\ZenData

(2) バイナリファイルのコピー

エンジンフォルダ Engine\Binaries\Win64 の中にある zen.exe と zenserver.exe を C:\zen\ZenInstall ににコピーします。

Epic Launcher 版エンジンを使用している場合は以下のようなパスになるかと思います。もちろん GitHub 版(ソースコード版)でも構いません。その場合はコピー元のバスを置き換えてください。

C:\Program Files\Epic Games\UE_5.5\Engine\Binaries\Win64\zenserver.exe
C:\Program Files\Epic Games\UE_5.5\Engine\Binaries\Win64\zen.exe

C:\zen\ZenInstall\zenserver.exe
C:\zen\ZenInstall\zen.exe

にコピーする。

(3) zen_config.lua ファイルを用意します

以下の内容で zen_config.lua ファイルを作成し、C:\zen\ZenInstall\zen_config.lua に置きます。

-- Zen Store Lua config

server = {
	dedicated = true,
	datadir = "C:\\zen\\ZenData",
	abslog = "C:\\zen\\ZenData\\local.log",
	debug = false,
	sentry = {
		disable = true,
		allowpersonalinfo = false,
	}
}

network = {
	httpserverclass = "httpsys", -- httpsys|asio
	port = 18558,
}

gc = {
	intervalseconds = 28800, -- every 8 hour
	lightweightintervalseconds = 3600, -- every hour
	cache = {
		maxdurationseconds =  864000, -- 10 days
	}
}

cache = {
	enable = true,
	accesslog = false,
	upstream = {
		upstreamthreadcount = 4,
		policy = "disabled", -- readwrite|readonly|writeonly|disabled
	},
	memlayer = {
		targetfootprint = 1073741824, -- 1 GB
		triminterval = 120, -- max every 2 minutes
		maxage = 172800, -- 2 days
	}
}

datadir, abslog のパスは必要に応じて書き換えてください。

ポート番号はデフォルトで 8558 ですが、これはローカルの ZenServer でも使用します。同じ PC 上で Unreal Editor も走らせる可能性がある場合はポート番号を変更します。今回の例では 18558 に置き換えました。

(4) netsh コマンドの実行

スタートボタン右クリックから「ターミナル(管理者)」を実行します。その後ターミナル内の PowerShell で以下のコマンドを実行します。

netsh http add urlacl url=http://*:18558/ user=$Env:USERNAME

設定結果の確認は「netsh http show urlacl」でできます。間違えた場合は「netsh http delete urlacl url=http://*:18558/ 」で削除してからやり直すことができます。

(5) firewall の設定

  1. スタートメニューで検索欄に「fire」を入力して「Windows Defender ファイアウォール」を起動します。(または 設定画面の検索から「ファイア」→「Windows Defender ファイアウォール」)
  2. 左側の「詳細設定」をクリックしてファイアウォールのダイアログを開きます
  3. 左上の「受信の規則」を選択して、右側の “操作” の中から「新しい規則…」をクリックします
  4. 規則の種類で「ポート」を選択して「次へ」
  5. 特定のローカルポートに「18558」を入れて「次へ」
  6. 「接続を許可する」が選択されていることを確認して「次へ」
  7. 選択しているネットワークの種類に応じて変更します。もしよくわからない場合はデフォルトの全部選択されてるまま「次へ」
  8. 名前を入力できるので「Zen DDC Server」を入れて「完了」

他のファイアウォールソフトウエアを使用している場合は、そちらの設定も行っておいてください。

(6)バッチファイルによる起動

これで完了です。あとは以下のようなバッチファイルを用意して実行するだけです。インストールフォルダが異なる場合は、パスを正しいものに書き換えてください。

@echo off

C:\zen\ZenInstall\zenserver.exe --config=C:\zen\ZenInstall\zen_config.lua

pause

もしこの状態で自動起動させたい場合はショートカットをスタートアップに入れておきます。

C:\Users\ユーザー名\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup

個人で使う分にはこれで十分だと思いますが、サービスとして起動することもできます。とりあえず先に動作確認してからサービスで起動する方法を解説します。

動作確認

  1. サーバーを起動した PC のブラウザで以下のページを開くことができるか確認します。
    • http://localhost:18558/dashboard
  2. 次に、他の PC からも開けるか確認します。
    • http://<インストールしたPCのIPアドレス>:18558/dashboard
    • 例えば Zen Server を起動した PC が 192.168.0.4 なら 「 http://192.168.0.4:18558/dashboard 」です。

ここでなにか設定できるわけではないので、それぞれページが表示されたら OK です。

UE5 の設定と確認

(1) Shared DDC の設定

プロジェクト側で設定する場合は Config/DefaultEngine.ini に、エンジン側で設定する場合は Engine/Config/BaseEngine.ini の最後に以下の行を追加してください。

[StorageServers]
Shared=(Host="192.168.0.4:18558", Namespace="ue.ddc", EnvHostOverride=UE-ZenSharedDataCacheHost, CommandLineHostOverride=ZenSharedDataCacheHost, DeactivateAt=60)

Host= の IP アドレスの部分は、Zen Storage Server を起動した PC の IP アドレスに置き換えてください。上の例で “192.168.0.4” となっている部分を置き換えます。

(2) Editor の起動と確認

  1. 何らかのプロジェクトで Editor を起動します。
  2. エディタの右下にある「派生データ」から「キャッシュ統計情報を表示」を選択します
  3. ダイアログが開くので、表示の中に「Zen リモート」が含まれていれば OK です

サービスとして起動する

起動バッチファイルを使わずに、サービスとして自動的に走らせておくことができます。もしサービス化する場合は、先にバッチファイルで起動した Zen Server をクローズし、スタートアップフォルダに作ったショートカットも削除しておいてください。

(1) サービスの登録

スタートボタン右クリックから「ターミナル(管理者)」を開いて、以下のコマンドを実行します。C:\zen\ZenInstall のパス部分は必要に応じて置き換えてください。

sc.exe create "Zen Store" start=auto binpath="C:\zen\ZenInstall\zenserver.exe --config=C:\zen\ZenInstall\zen_config.lua"

続けて以下のコマンドも実行します。

sc.exe failure "Zen Store" reset=60 actions=restart/60000

(2) サービスの設定

  1. スタートボタン右クリックから「コンピューターの管理」を開きます
  2. 「サービスとアプリケーション」の中にある「サービス」を選択します
  3. サービス一覧の中から「Zen Store」を探してダブルクリックします
  4. 「ログオン」のタブを選択し、下側の「アカウント」を選択します
  5. アカウント欄右側の「参照」を開いて、入力欄に自分のユーザー名を入れて「名前の確認」をクリックします
  6. 名前が展開されたら「OK」をクリックします
  7. ログインパスワードを入れて「適用」をクリックします
    • ここで「アカウント ~ にサービスとしてログオンする権利が与えられました。」とダイアログ表示が出れば成功です
  8. 「全般」タブに切り替えて「開始」します

これでサービスとして自動的に起動するようになりました。

もし「サービスとしてログオンする権利が与えられました。」が表示されない場合

Windows 11 Pro の場合は以下のようにします

  1. スタートメニューを表示し、検索欄に「ローカル」を入力して「ローカルセキュリティポリシー」を起動します
  2. 「セキュリティの設定」 → 「ローカルポリシー」 → 「ユーザー権利の割り当て」 → 「サービスとしてログオン」をダブルクリックします
  3. 「ユーザーまたはグループの追加」をクリックします
  4. 自分のユーザー名を入力して「名前の確認」を押します
  5. 名前が展開されたら「OK」→「OK」をクリックして閉じます

Windows 11 Home の場合は上の設定ができません。サービスとして起動したい場合は公式のドキュメントに従い、別のローカルユーザーを作成してみてください。もしくは個人で使う場合はサービス化しなくても、バッチファイルによる起動のままでも十分だと思います。

設定の調整など

週末しか使用しないなど、Unreal Engine の利用頻度が低い場合は zen_config.lua 内の期限設定を長めに変更した方が良いかもしれません。

Pixel 9a Tensor G4 の浮動小数点演算能力と Linux ターミナル

Pixel 9a で vfpbench を走らせてみました。vfpbench は CPU の浮動小数点演算能力の理論的なピーク値に焦点を当てたベンチマークです。

以下の表は Pixel 8/8a との比較のための抜粋です。動作クロックが上がっている分だけシングル性能は高いはずですが、1コア減っているためマルチスレッドでは差がつきません。Pixel 8 比では全体的に低い値になっています。Pixel 8a の Single (Cortex-X3) の値が極端に低いですが、おそらく測定時に発熱で制限(サーマルスロットリング)がかかり、クロックが上がらなかったためと思われます。

fp32 SingleFP32 MULTIFP64 SINGLEFP64 MULTI
Pixel 869.7 GFLOPS281.9 GFLOPS28.0 GFLOPS139.6 GFLOPS
Pixel 8a37.7 GFLOPS245.1 GFLOPS18.8 GFLOPS122.2 GFLOPS
Pixel 9a67.9 GFLOPS256.5 GFLOPS33.8 GFLOPS127.4 GFLOPS
SINGLE = Single Thread、MULTI = Multi Thread

全部のデータはこちらで参照できます。

個々の命令の特性を見ると、クロックあたりのピークの浮動小数点演算能力はほぼ同等で特性もかなり似通ったものになっていることがわかります。

Tensor G4 自体は G3 と比べると CPU コアの世代が上がっています。以下は CPU コアの比較表です。

TENSOR G1TENSOR G2TENSOR G3TENSOR G4
PrimeX1 (x2)X1 (x2)X3 (x1)X4 (x1)
BigA76 (x2)A78 (x2)A715 (x4)A720 (x3)
LittleA55 (x4)A55 (x4)A510 (x4)A520 (x4)

Tensor G3 で唯一 32bit 命令2対応していた A510 が無くなり、Tensor G4 では完全に 64bit 命令のみ対応の CPU コアに置き換わりました。Tensor G4 では ARM の 32bit 命令のプログラムは動きません。ARM の各 CPU コアの 32bit 命令対応についてはこちらの記事を参照してください。

もっとも、OS としては Pixel 7 の Tensor G2 世代から 32bit アプリケーションには非対応となっており、すでに完全に 64bit に置き換わっています。そのため 32bit 対応コアがなくなっても影響はありませんのでご安心ください。

vfpbench の話しに戻ります。Tensor G4 の LITTLE コア A520 は 4個搭載されていますが、シングル時の浮動小数点演算性能に対して、4コアマルチスレッドでも 4倍ではなく 2倍にしかなっていません。 以下は LITTLE コアだけの比較になります。

FP32 SINGLEFP32 MULTIFP64 SINGLEFP64 MULTI
Pixel 7a (A55)14.0 GFLOPS54.7 GFLOPS7.0 GFLOPS27.8 GFLOPS
Pixel 8 (A510)27.1 GFLOPS61.3 GFLOPS13.5 GFLOPS29.1 GFLOPS
Pixel 8a (A510)27.0 GFLOPS56.6 GFLOPS13.5 GFLOPS28.0 GFLOPS
Pixel 9a (A520)30.9 GFLOPS62.7 GFLOPS15.4 GFLOPS31.7 GFLOPS
SINGLE = Single Thread、MULTI = Multi Thread

例えば Pixel 9a (A520) の FP32 SINGLE は 30.9 GFLOPS ですが、FP32 MULLTI でも約 2倍の 62.7 GFLOPS しかありません。これは A520 が A510 と同じように 2コアで浮動小数点演算ユニットを共有しているためだと考えられます。

A55 時代の Pixel 7a (Tensor G2) では Multi 時のスコアに対して Single の値が 1/4 になっています。つまり A510/A520 は A55 と比べて Single 時の性能が 2倍になっているわけです。

また LITTLE コアだけの比較では Pixel 8/8a の G3 よりも Pixel 9a の G4 の方が速度が上がっています。それぞれクロック差の影響がきちんとスコアに反映されています。同様に同じ G3 を搭載した Pixel 8 と 8a のパフォーマンスも同等です。LITTLE コアは電力効率が良いためにサーマルスロットリングの影響を受けなかったのだと思われます。

A510 におけるコアの共有についてはこちらで解説しています。

Linux 開発環境 (ターミナル) が 9a で使えないことについて

Pixel 9a を実際に使ってみて少々予想外だった点は、Linux 開発環境 (ターミナル) 機能が使えなかったことです。

「Linux 開発環境」は Pixel の OS に標準で含まれている Linux のコマンドラインの動作環境です。ChromeOS の同名の機能、もしくは Windows の WSL に相当します。Linux 開発環境 (ターミナル) 機能については以下の記事で解説しています。

おそらく使えないのは発売当初だけで、将来の OS 更新によって Pixel 9a でもサポートするのではないかと思われます。

幸いなことに、発売したばかりの Pixel 9a も Android 16 のベータプログラムに含まれていることがわかりました。Pixel 9a でも Android 16 Beta 4 をインストールすると、開発者向けオプショにから Linux 開発環境を有効にすることができました。

どうしても今すぐ Pixel 9a で Linux を使いたいという場合はベータプログラムを利用するのも一つの手かもしれません。もちろんメインのスマートフォンとして使用している場合はお勧めしません。

MCP Server の仕組みを少し調べてみる

LLM をチャットの応答だけでなく、Agent として使うために直接外部アプリケーションを呼び出せるような拡張が行われています。特に MCP と呼ばれるプロトコルではツールとのインターフェースが標準化されており、SDK を使うと簡単に追加機能を作成することが可能です。

PC 上で動いているクライアントアプリケーションは、人間の入力を LLM が動いているサーバーに送信して返答を受け取ります。Agent ではその一連のやり取りにツールが割り込みます。LLM からの要請に応じてクライアント側がツールのソフトウエアを呼び出し、人間の代わりに LLM に対して返答するわけです。これらの Function Calling と呼ばれる機能拡張の仕組みを標準化したものが MCP に相当します。

MCP に対応したツールはサーバーと呼ばれるため、クラウド上に用意したり、LLM サーバー側が直接通信しているような印象を受けますが実際は異なります。簡単に言えば PC 上で動いている LLM アプリケーションに追加するプラグインのことです。

Claude Desktop や Cline などのソフトウエアは、プラグインのロードと同じように組み込まれている MCP のソフトウエアを別プロセスとして起動します。このときプロセス間通信として、PIPE (標準入出力) もしくは TCP (HTTP/SSE) が使われています。

MCP サーバーはクライアント毎に別プロセスが立ち上がります。例えば Claude Desktop と Cline のどちらも同じ MCP のツールを参照していた場合、それぞれが別プロセスとして MCP サーバーを起動します。サーバーは共有されません。やはり構造的にプラグインの方がイメージしやすいように思います。

Python SDK MCP コマンド

PIPE や TCP で渡されるデータは Json です。Python SDK で使われている mcp コマンドは、この Json と Python Script の関数呼び出しの相互変換を行っています。

例えば以下の例では mcp コマンド (mcp.exe) が標準入力から json フォーマットの文字列を受け取り、関数呼び出しの形に変換して server.py 内部の関数呼び出します。また関数の戻り値を json 化して標準出力に出力します。

{
  "mcpServers": {
    "demo-app": {
      "command": "mcp",
      "args": [
        "run",
        "C:\\mcptest\\server.py"
      ]
    },
  }
}

mcp.exe は Python の実行ファイルで、引数で渡されている server.py を内部で import しています。

実際にやり取りされているデータ

本当に標準入出力が使われているのかどうか、間に別のプロセスを挟み込んで通信内容をキャプチャしてみました。引数で渡した mcp サーバーを起動し、標準入出力をそのまま渡します。同時にログファイルに記録します。このコマンド (command-capture.py) は Calude 3.7 Sonnet が作りました。

{
  "mcpServers": {
    "demo-app": {
      "command": "C:\\mcptest\\venv\\Scripts\\python.exe",
      "args": [
        "C:\\mcptest\\command-capture.py",
            "--quiet",
            "--log-dir",
                "C:/mcptest/logs",
            "C:\\mcptest\\venv\\Scripts\\mcp.exe",
                "run",
                "C:\\mcptest\\server.py"
      ]
    }
  }
}

以下は Claude Desktop による実際の入出力を記録したものです。tool/list など method の呼び出しが行われている様子がわかります。

[2025-04-06 15:09:35.419] IN: {"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"claude-ai","version":"0.1.0"}},"jsonrpc":"2.0","id":0}
[2025-04-06 15:09:36.981] OUT: {"jsonrpc":"2.0","id":0,"result":{"protocolVersion":"2024-11-05","capabilities":{"experimental":{},"prompts":{"listChanged":false},"resources":{"subscribe":false,"listChanged":false},"tools":{"listChanged":false}},"serverInfo":{"name":"demo-app","version":"1.5.0"}}}
[2025-04-06 15:09:36.988] IN: {"method":"notifications/initialized","jsonrpc":"2.0"}
[2025-04-06 15:09:36.989] IN: {"method":"resources/list","params":{},"jsonrpc":"2.0","id":1}
[2025-04-06 15:09:36.990] IN: {"method":"tools/list","params":{},"jsonrpc":"2.0","id":2}
[2025-04-06 15:09:36.992] OUT: {"jsonrpc":"2.0","id":1,"result":{"resources":[]}}
[2025-04-06 15:09:36.992] OUT: {"jsonrpc":"2.0","id":2,"result":{"tools":[{"name":"calc_add","description":"Add two numbers","inputSchema":{"properties":{"a":{"title":"a","type":"string"},"b":{"title":"b","type":"string"}},"required":["a","b"],"title":"calc_addArguments","type":"object"}},{"name":"exec_shell_command","description":"Execute a command in the bash shell","inputSchema":{"properties":{"command":{"title":"command","type":"string"}},"required":["command"],"title":"exec_shell_commandArguments","type":"object"}}]}}

[2025-04-06 15:10:53.116] IN: {"method":"tools/call","params":{"name":"calc_add","arguments":{"a":"2838414","b":"8294241"}},"jsonrpc":"2.0","id":36}
[2025-04-06 15:10:53.118] OUT: {"jsonrpc":"2.0","id":36,"result":{"content":[{"type":"text","text":"11132655"}],"isError":false}}

なおアプリケーション側でも同様のログが記録されているため、デバッグに利用する場合はこのようなツールは不要です。Claude Desktop の Windows 版の場合 AppData\Roaming\Claude\logs にあります。

Json 部分を整形すると以下のようになります。

[2025-04-06 15:09:35.419] IN: {
    "method": "initialize",
    "params": {
      "protocolVersion": "2024-11-05",
      "capabilities": {},
      "clientInfo": {
        "name": "claude-ai",
        "version": "0.1.0"
      }
    },
    "jsonrpc": "2.0",
    "id": 0
  }
[2025-04-06 15:09:36.981] OUT: {
    "jsonrpc": "2.0",
    "id": 0,
    "result": {
      "protocolVersion": "2024-11-05",
      "capabilities": {
        "experimental": {},
        "prompts": {
          "listChanged": false
        },
        "resources": {
          "subscribe": false,
          "listChanged": false
        },
        "tools": {
          "listChanged": false
        }
      },
      "serverInfo": {
        "name": "demo-app",
        "version": "1.5.0"
      }
    }
  }
[2025-04-06 15:09:36.988] IN: {
    "method": "notifications/initialized",
    "jsonrpc": "2.0"
  }
[2025-04-06 15:09:36.989] IN: {
    "method": "resources/list",
    "params": {},
    "jsonrpc": "2.0",
    "id": 1
  }
[2025-04-06 15:09:36.990] IN: {
    "method": "tools/list",
    "params": {},
    "jsonrpc": "2.0",
    "id": 2
  }
[2025-04-06 15:09:36.992] OUT: {
    "jsonrpc": "2.0",
    "id": 1,
    "result": {
      "resources": []
    }
  }
[2025-04-06 15:09:36.992] OUT: {
    "jsonrpc": "2.0",
    "id": 2,
    "result": {
      "tools": [
        {
          "name": "calc_add",
          "description": "Add two numbers",
          "inputSchema": {
            "properties": {
              "a": {
                "title": "a",
                "type": "string"
              },
              "b": {
                "title": "b",
                "type": "string"
              }
            },
            "required": [
              "a",
              "b"
            ],
            "title": "calc_addArguments",
            "type": "object"
          }
        },
        {
          "name": "exec_shell_command",
          "description": "Execute a command in the bash shell",
          "inputSchema": {
            "properties": {
              "command": {
                "title": "command",
                "type": "string"
              }
            },
            "required": [
              "command"
            ],
            "title": "exec_shell_commandArguments",
            "type": "object"
          }
        }
      ]
    }
  }



[2025-04-06 15:10:53.116] IN: {
    "method": "tools/call",
    "params": {
      "name": "calc_add",
      "arguments": {
        "a": "2838414",
        "b": "8294241"
      }
    },
    "jsonrpc": "2.0",
    "id": 36
  }
[2025-04-06 15:10:53.118] OUT: {
    "jsonrpc": "2.0",
    "id": 36,
    "result": {
      "content": [
        {
          "type": "text",
          "text": "11132655"
        }
      ],
      "isError": false
    }
  }

標準入出力ができれば良いだけなので、SDK やライブラリがない他の言語でも比較的容易に作ることができる仕組みです。