前回はAI市場の動向(p934)を調べ、その中で「クラウド型AIは便利だが有料・トークン消費が課題」「ローカルLLMが実用域に入ってきた」という話をしました。今回はその続きとして、“自分のPCを操作してくれるAIエージェント”を、完全ローカル(ネット上のAIに頼らない)で作ってみます。使うのは2025年末に出た新しめのローカルモデル Ministral 3 14B です。
・ローカルLLM(Ministral 3 14B・Q4)に“道具”を持たせてエージェント化する方法
・Web検索・ファイル読み書き・PC操作(マウス/キーボード)・RAG記憶・画像理解を1つのアプリに統合
・さらにCLI/MCP操作(Unity・Blender向け)とClaude Code連携、古い知識の自動更新も
・暴走させないための緊急停止と重要操作の確認の作り方
・Mac(M4)での実機動作・つまずき・対処。コードと設定値つき
作るもの:完全ローカルのAIエージェント
完成したのがこの「ローカルAIエージェント」。見た目はシンプルなチャットアプリですが、中身はネットに繋がっていなくても(モデルは手元・検索だけ任意でネット利用)動く、道具を使えるAIです。

このアプリ1つで、次のことがすべて手元のPCの中でできます。
- テキストで質問・相談(雑談や計算はそのまま回答)
- 知らないことはWeb検索して答える(検索結果は学習データに蓄積)
- ファイルを読む・書く(txt/csv/xlsx/pdf/画像)
- PCを操作(マウス・キーボード・画面)=ここがエージェントの肝
- コマンド(CLI)やMCPで操作:Unity・Blenderなどを画面クリックより正確・高速に
- Claude Codeに委譲:難しいコーディングはクラウドの強力なAIへ任せる
- 記憶(RAG):覚えた知識や指示を次回に活かす/古くなったら自動で再検索・更新
- 画像を理解(写真やグラフを読む)
そして強い機能だからこそ、いつでも止められる・勝手にやらせないという安全装置も入れています(後述)。
なぜ作る?クラウド型エージェントの“有料・消費”問題
最近は「PC操作までやってくれるAIエージェント」のサービスが増えました。とても便利ですが、本格的に使おうとすると――
- 有料プランが前提:常用するなら月額や従量課金がかかる
- トークン消費が膨大:PCの作業を任せるほど、AIに送る文章量が増えて消費が跳ね上がる
- プライバシー:画面やファイルの内容を外部に送ることになる
前回(p934)で見たとおりローカルLLMは急速に進化しています。「日常のPC作業の補助くらいなら、手元のAIで十分では?」――これを確かめるのが今回の目的です。完全ローカルなら無料・無制限・プライバシーも安心です。
全体構成と用意するもの
構成はこの通り。p933と同じ llama-cpp-python を土台に、道具とGUIを足してエージェントにします。
| 部品 | 役割 |
|---|---|
| Ministral 3 14B(gguf・Q4) | 頭脳。Mistral AIが2025年末に公開した、画像も読める高性能ローカルモデル |
| llama-cpp-python(MTMD) | モデルを動かす。道具(function calling)と画像を1インスタンスで両対応 |
| PySide6 | デスクトップGUI(Windows・Mac共通) |
| pyautogui | マウス/キーボード/画面の操作(+緊急停止のFAILSAFE) |
| sentence-transformers | RAG用の文章ベクトル化(多言語e5・日本語対応) |
| ddgs / openpyxl / pypdf | Web検索/Excel・PDFの読み取り |
| subprocess / 自前MCPクライアント | CLIコマンド実行/MCPサーバ連携(Unity・Blender等) |
| claude CLI | 難しい実装をClaude Codeに委譲する連携(任意) |
モデルはQ4量子化で約8.2GB。画像用の補助ファイル(mmproj)が約0.9GB。RTX3060のVRAM 12GBに収まり、M4/32GBでも余裕です。
# 必要ライブラリ pip install llama-cpp-python PySide6 pyautogui sentence-transformers ddgs openpyxl pypdf # モデル本体(Q4_K_M 約8.2GB)と画像用mmproj(約0.9GB)をダウンロード # from: huggingface.co/unsloth/Ministral-3-14B-Instruct-2512-GGUF # Ministral-3-14B-Instruct-2512-Q4_K_M.gguf # mmproj-F16.gguf
※ Windowsで RTX3060のGPU を使うときは、CUDA対応版の llama-cpp-python を入れます(環境変数 CMAKE_ARGS=-DGGML_CUDA=on でビルド、または対応wheel)。Macは追加設定なしでGPU(Metal)が使われます。
実装①:Ministralに“道具”を持たせる(function calling)
エージェントの核心は「AIに道具を持たせ、必要なときだけ自分で使わせる」こと。Ministral 3はfunction calling(道具呼び出し)に対応しているので、道具の一覧を渡すだけで「検索が要るか/自分で答えられるか」をAIが判断してくれます。
ポイントは、モデルに付属のテンプレートを使うこと。llama-cpp-pythonのMTMDハンドラでモデルとmmprojを読み込むと、道具呼び出しと画像理解の両方が1つのインスタンスで動きます(VRAM12GBに収めるうえで重要)。
from llama_cpp import Llama
from llama_cpp.llama_chat_format import MTMDChatHandler
handler = MTMDChatHandler(clip_model_path="models/mmproj-F16.gguf") # 画像対応
llm = Llama(model_path="models/Ministral-3-14B-Instruct-2512-Q4_K_M.gguf",
n_ctx=8192, n_gpu_layers=-1, chat_handler=handler) # -1=全部GPUへ
# 道具の定義(JSONスキーマ)。これを渡すだけでAIが使い分ける
tools = [{"type":"function","function":{
"name":"web_search","description":"最新情報や知らない情報をネット検索する",
"parameters":{"type":"object","properties":{"query":{"type":"string"}},"required":["query"]}}}]
out = llm.create_chat_completion(
messages=[{"role":"system","content":"必要なら道具を使う日本語アシスタント"},
{"role":"user","content":"今日の東京の天気を調べて"}],
tools=tools, tool_choice="auto")
このモデルは道具を使うとき、標準の
tool_callsではなく web_search{"query":"…"} のような形でも返してきました。そこで「tool_calls / name{json} / {"tool":…} のどれでも拾える」パーサを書いて吸収しています。これで「天気→検索する」「計算→そのまま答える」を安定して判断するようになりました。
実装②:エージェントのループと安全機構
エージェントは「考える→道具を使う→結果を見てまた考える」をくり返します(ReActと呼ばれる方式)。無限ループや暴走を防ぐため、道具の使用回数に上限を設けます。
for step in range(MAX_STEPS): # 道具の使用回数に上限(暴走防止)
self.stop.checkpoint() # ← 緊急停止が押されていたら即中断
msg = llm.chat_message(messages, tools=TOOLS)
name, args = parse_tool_call(msg)
if not name: # 道具を使わない=最終回答
return msg["content"]
result = self.run_tool(name, args) # 道具を実行(危険操作は確認を挟む)
messages.append({"role":"user","content": f"[ツール結果]\n{result}"})
PCを操作できるAIは強力なので、2本の安全装置を必ず入れました。
(1) 緊急停止:いつでも止められるようにします。①画面のSTOPボタンとEscキー、さらに②pyautoguiのFAILSAFE(マウスを画面の四隅に勢いよく当てると例外で即停止)。ループの要所でcheckpoint()を呼び、停止要求が出ていたら処理を打ち切ります。
import pyautogui pyautogui.FAILSAFE = True # マウスを画面四隅へ=物理的な非常ブレーキ pyautogui.PAUSE = 0.3 # 各操作の間に必ず間を空ける(人が割り込める)
(2) 重要操作の確認:ファイル書き込み・クリック・入力・「削除/送信」などの取り返しのつかない操作の前に、必ず確認ダイアログを出します。さらに、マウス/キーボード操作は画面下の「PC操作を許可」トグルがONのときだけ動くようにし、普段は誤操作しないようにしています。

実装③:Web検索・RAG記憶・ファイル・画像理解
残りの道具も、それぞれ小さな部品にしてエージェントに持たせます。
- Web検索:
ddgs(DuckDuckGo)でAPIキー不要・無料。検索結果はそのまま記憶(RAG)に蓄積して、次回以降に再利用します(=“学習”)。 - RAG記憶:文章を多言語e5でベクトル化し、SQLiteに保存。質問が来たら意味の近い記憶を思い出して回答に添えます。学習データのリセットもボタン1つ。
- 恒久メモリ:「常体で答えて」等のずっと守る指示を保存し、毎回プロンプト先頭に差し込みます。
- ファイル:txt/csv/xlsx(openpyxl)/pdf(pypdf)/画像を読み、結果をファイルに書き出し。
- 画像理解:mmprojのおかげで写真やグラフを読めます(後述のデモ参照)。
# RAG記憶(要点):文章をベクトル化してSQLiteへ。質問時は意味の近い順に思い出す
def remember(self, text):
vec = self.embed(text) # multilingual-e5 で数値ベクトル化
db.execute("INSERT INTO knowledge(text, vec) VALUES(?,?)", (text, vec.tobytes()))
def recall(self, query, k=3):
qv = self.embed(query)
scored = [(float(np.dot(qv, v)), t) for t, v in all_rows] # コサイン類似度
return sorted(scored, reverse=True)[:k] # 近いものを上位k件
動かす:検索・記憶・画像・PC操作
実際に使ってみます。まずは「知らないことはWeb検索して答える」。下の例では、最新モデルの情報を自分で検索し、結果を要約しています(道具の使用が黄色で見えます)。

検索した内容は記憶(RAG)に貯まるので、あとで「さっき調べたこと、思い出して」と言うと、ちゃんと引っ張り出してまとめてくれます(右下の「記憶: 知識3」がそれ)。

画像も読めます。手元の売上グラフ画像を渡して「読んで傾向を教えて」と頼むと――

そして本命のPC操作。「入力欄をクリックして、この文を入力して」と頼むと、AIが自分でclick→type_textの道具を選び、確認を経て実行します。

使い勝手も少し整えました。14Bは応答に少し時間がかかるので、「今は処理中か/次を入力してよいか」がひと目で分かるインジケータを付けています(処理中はオレンジ・入力できるときは緑)。回答は改行や箇条書きで読みやすく整形し、チャットをクリアするボタンも用意しました。

発展:知識の更新・CLI/MCP・Claude Code連携
ここまでで“使える”エージェントになりましたが、実際に使い込むと欲しくなる機能を3つ足しました。
(1) 古い知識を自動で更新する。検索で溜めた知識は時間が経つと古くなります。そこで各記憶に保存日時を持たせ、7日を過ぎたweb由来の知識は「古い情報」と印を付けます。AIは古い記憶を見つけると、refresh_knowledge で古い記憶を消して再検索→最新で上書きします。
def refresh_knowledge(query):
removed = memory.forget(query) # queryに近い古い記憶を削除(重複防止)
results = web_search(query) # 最新を取り直す
for r in results: memory.remember(r) # 新しい知識として保存し直す
(2) 画面操作の代わりにCLI/MCPで操作する。UnityやBlenderのような重いアプリは、マウスでカチカチやるより“コマンド”で動かす方が速くて正確です。そこで2つの道具を追加しました。
- run_command(CLI):シェルコマンドを実行。例:
blender --background --python script.pyやUnity -batchmode -executeMethod Build.Run。 - mcp_call(MCP):MCP(Model Context Protocol)は、AIに外部ツールを提供する共通規格。BlenderやUnity用のMCPサーバを繋げば、その道具をそのままAIが使えます。今回は依存を増やさず自前の軽量MCPクライアントを書き、繋いだサーバの道具を“エージェントの道具”として自動登録しました。

※ MCP設定は mcp_config.json(Claude Desktopと同じ形式)に書くだけ。記事では動作確認用の小さなデモMCPサーバを用意しましたが、ここを blender-mcp / unity-mcp などの本物のサーバに差し替えれば、そのまま3D制作に使えます。
(3) 難しい実装はClaude Codeに任せる。ローカルLLM(14B)は賢くなったとはいえ、本格的なコーディングはまだクラウドの上位AIに分があります。そこで「司令塔はローカル、重い実装はClaude Code」というハイブリッドにしました。claude_code 道具が claude -p "指示" を呼び出し、結果を受け取ります。
def claude_code(prompt): # Claude Code(CLI)に委譲
out = subprocess.run(["claude", "-p", prompt, "--output-format", "json"], ...)
return json.loads(out.stdout)["result"] # 実装やコードレビューを任せて結果を受け取る
普段の調べもの・ファイル整理・PC操作は手元のMinistralで無料・無制限、ここぞの実装だけClaude Codeに依頼――と使い分けられます。
つまずきポイントと対処
- 道具を使ってくれない:最初はシステムプロンプトで「JSONを出して」と頼む方式にしたら、知っている質問では検索せず勝手に答えてしまいました。→ モデル付属のテンプレート+tools=(function calling)に切り替えたら、検索/直答の判断が安定しました。
- tool_callsが空で返る:道具呼び出しが
web_search{...}という独自形で返ることがあり、標準フィールドが空でした。→ 複数形式に対応するパーサで解決。 - macOSで操作が無視される:Macではpyautoguiのクリック/入力が静かに無視されることがあります(エラーも出ない)。原因は権限で、システム設定 > プライバシーとセキュリティ > アクセシビリティ(と画面収録)でアプリ(実行元のターミナル等)を許可すると動きます。最初の関門なので要注意。
- 14Bは速くはない:M4(32GB)で約11トークン/秒、読み込み約5秒。3Bクラス(p933は約38 tok/s)より遅いですが、賢さは上。用途で選ぶのがよいです。
- 終了時のクラッシュ報告:Metalの後始末で終了時に警告が出ることがあり、
os._exit(0)でクリーンに閉じるようにしました(p933と同じ対処)。 - VRAMに収める:14BはQ4でも約8.2GB。画像用mmprojと合わせ、RTX3060の12GBに収まる量子化(Q4_K_M)を選ぶのがコツです。
- MCPの道具を呼べない:最初はMCPの道具をシステムプロンプトで“紹介”しただけだと、AIが
system_infoを直接呼ぼうとして「未知の道具」になりました。→ MCPの道具を“第一級の道具”として動的登録(名前→サーバの対応表で実行)したら、自然に使えるように。 - Claude Code連携の認証:
claudeCLIは普通のターミナルからは正常に動きますが、Claude Codeのセッション内から呼ぶと認証エラー(401)になることがあります。アプリ単体起動/通常のターミナルから使うのが安全です。
Windowsでも動かす(RTX3060で検証)
ここまではMac(M4)の話でした。まったく同じコードを Windows 11(RTX3060・VRAM12GB)でも動かして検証しました。結論、ほぼそのままで全機能が動作。GPU(CUDA)にもモデルが全41層フルに載りました(VRAM約9.3GBで12GBに収まる)。
| 項目 | Mac(M4 / 32GB) | Windows(RTX3060 / 12GB) |
|---|---|---|
| モデル読込 | 約5秒 | 約3.8〜5.7秒 |
| 生成速度 | 約11 tok/s | 約6.3〜7.3 tok/s |
| GPU | Metal | CUDA・全41層・VRAM約9.3GB |
| PC操作(マウス/キーボード) | 権限の許可が必要 | 権限不要で動作 |
| 全機能 | OK | OK |
※ 生成速度はMacの方が速め。WindowsはRTX3060でも、今回使ったCUDA版ビルドの都合で伸び切らず(それでも会話には十分)。読込・GPU動作・機能面はMacと遜色なし。
個人的にうれしかったのがPC操作です。Macは権限の都合で“入力しようとする”ところまででしたが、Windowsは特別な権限なしで、実際にメモ帳へ文字が入力されました。「AIが自分のPCを操作する」が目に見える形で動いた瞬間です。

CLIやMCPもWindowsネイティブのまま動作。下は ver コマンドとMCPの system_info を実行したところです。

そしてスタートメニュー/デスクトップのショートカットからも、アイコンをクリックするだけで起動できました。

Windows特有のつまずきもいくつかありました。代表的なのは――
- CUDA版llama-cpp-pythonのDLL不足:プリビルド版だけだと起動時に
FileNotFoundError。→pip install nvidia-cuda-runtime-cu12 nvidia-cublas-cu12でCUDAランタイムを補い、DLLを配置して解決(CUDA Toolkit本体は不要)。 - アイコン起動(pythonw)でコンソール窓がちらつく+MCPがエラー:コンソールなしで起動すると、子プロセス(MCP・コマンド実行・日本語貼り付け)が黒い窓を一瞬開き、MCPの呼び出しが
[Errno 22]で失敗。→ 全てのサブプロセスにWindows用フラグCREATE_NO_WINDOWを付与して、窓ゼロで全機能が動くようにしました(このコード修正はMac/Linuxでは無影響)。 - PowerShellの文字化け:Mac作成のスクリプトがBOM無しで日本語がパースエラー → UTF-8 BOM付き保存で解決。
- 確認ダイアログにキー入力を奪われる:メモ帳へ入力する直前に承認した確認ダイアログ(=アプリ側の窓)が前面に残り、文字がアプリに入ってしまうことが。→ 「最後に使っていた外部ウィンドウ」を常に記憶しておき、入力の直前にそのウィンドウを前面へ戻してから打つことで解決(Windowsのみの処理)。
いずれも対処できて、「Mac/Windowsどちらでも、同じローカルAIエージェントが同じように使える」ことが確認できました。
まとめ
ローカルLLM(Ministral 3 14B)に道具を持たせるだけで、検索・ファイル・PC操作・記憶・画像理解までこなすAIエージェントが、完全ローカルで作れました。クラウド型のような“最高の賢さ”はありませんが、無料・無制限・プライバシー安心で、日常のPC作業の相棒としては十分に実用的です。
- function callingで「道具を使うか/自分で答えるか」をAIが判断
- 緊急停止+確認ダイアログ+許可トグルで、強い機能を安全に使う
- RAG記憶で検索結果や指示を学習し、次回に活かす(古くなったら再検索で更新・リセットも可能)
- CLI/MCPでUnity・Blender等を正確に操作、難所はClaude Codeに委譲するハイブリッド
- Q4量子化でRTX3060(12GB)にも収まる=普段使いのPCで動く
今回はMac(M4)で構築し、Windows(RTX3060)でも実機検証しました(前章)。GPUはMac=Metal/Windows=CUDAで自動的に使われ、同じコードが両OSで動作。普段使いのPCで完結するローカルAIエージェントになりました。
最後に、毎回ターミナルから起動するのは面倒なので、普通のアプリのように起動できるようにしました。Macは .app 化してLaunchpad(アプリケーション)から、Windowsはスタートメニュー/デスクトップのショートカットから、アイコンをクリックするだけで立ち上がります。自作のローカルAIが“自分のPCの常駐アプリ”になると、ぐっと身近になりました。
それでは、今回はここまで。最後までありがとうございました😊