![]()
前回のレッスンではエージェントをクラウドにスケールアップしましたが、今回はそれを単一のマシンにスケールダウンします。最後には、推論が一切クラウドに呼ばれることなく、推論、ツール呼び出し、ファイルの読み込み、ドキュメント検索を行う実用的なエンジニアリングアシスタントが完成します。
なぜこれをやりたいのでしょうか?実際のエンジニアリング作業で頻繁に出てくる理由が3つあります:
ただし、これにはフロンティアのクラウドモデルと引き換えに、CPU、GPU、NPU上で動作する小型言語モデル(SLM)を使う必要があります。このレッスンは制約を無かったことにせず、その制約の中で良いエージェントを構築する方法について扱います。
このレッスンで学ぶ内容は以下の通りです:
このレッスンを修了すると以下ができるようになります:
このレッスンでは以下の内容を既に修了し、慣れていることを想定しています:
また以下が必要です:
requirements.txt に加え、本レッスン用に foundry-local-sdk、openai、chromadb をインストール。フロンティアのクラウドモデルは数千億パラメータとデータセンターを持ちますが、SLMは数十億パラメータでノートパソコンのRAMに収まるサイズです。この差が期待値を明確にします。
SLMが得意なこと:
SLMが苦手なこと:
したがってローカルエージェントの勝ち筋は: SLMはオーケストレーションに専念し、重い処理はツールに任せる ことです。モデルはコードベースそのものを知る必要はなく、read_fileやsearch_docsをいつ呼ぶべきかを知れば良い。これがSLMの強みを活かす戦術です。
flowchart LR
U[開発者] --> A[ローカル SLM エージェント]
A -->|どのツールを使うか決定する| T1[ファイルを読む]
A -->|どのツールを使うか決定する| T2[search_docs RAG]
A -->|どのツールを使うか決定する| T3[コードを解析する]
T1 --> A
T2 --> A
T3 --> A
A --> R[回答、完全にオンデバイスで]
Microsoft Foundry Local は、モデルをダウンロード、管理、提供までを完全にマシン上で行う軽量ランタイムです。重要な特徴は OpenAI互換のHTTPエンドポイント を提供することで、これによりOpenAI SDKやMicrosoft Agent FrameworkのOpenAIクライアントが base_url を変えるだけで動作します。エージェント構築の知識がそのまま使え、エンドポイントがクラウドから localhost に移るだけです。
Foundry Localは、CPUビルド、CUDA/GPUビルド、またはNPUビルドの中からハードウェアに最適なモデルビルドを自動選択するので、マシンごとの手動最適化は不要です。
Foundry Localをインストールし(お使いのOS向けのドキュメント参照)、動作を確認してください:
# インストール(例:プラットフォームのドキュメントに従ってください)
winget install Microsoft.FoundryLocal # Windows
# brew install microsoft/foundrylocal/foundrylocal # macOS
# Qwenモデルをダウンロードして実行し、その後ローカルサービスを開始します
foundry model run qwen2.5-7b-instruct
foundry service status
サービスが起動すると、通常 http://localhost:PORT/v1 のOpenAI互換エンドポイントが利用可能になります。ノートブックは foundry-local-sdk を使って自動的にエンドポイントを検出するため、ポートをハードコーディングする必要はありません。
エージェントはツールを呼び出せるからこそエージェントです。多くのSLMはチャットはできますが、信頼できる整形式のツール呼び出しを生成しません。Qwenモデルは関数呼び出し用に訓練されており、常に整形式のツール呼び出し構造を出力します。これがローカルチャットモデルをローカルエージェントに変える要素です。
フローは既知のツール呼び出しループそのもので、デバイス上で実行されているだけです:
sequenceDiagram
participant U as ユーザー
participant A as Qwen エージェント(ローカル)
participant T as ローカルツール
U->>A: 「auth.py は何をしますか?」
A->>A: 判断:read_file を呼び出す
A->>T: read_file("auth.py")
T-->>A: ファイルの内容
A->>A: 内容について推論
A-->>U: 説明
ドキュメント検索はローカルエージェントの価値を生み出す部分です。SLMがフレームワークのドキュメントを丸暗記していることに期待するのではなく、ドキュメントをローカルベクトルデータベースに埋め込み、必要に応じて関連部分を検索させます。
我々は Chroma を使います。Chromaはサーバー不要でプロセス内に埋め込めるベクトルストアです。パイプラインは完全にローカルです: ローカル埋め込みモデル → ローカルベクトル → ローカル検索 → ローカルSLM。
flowchart TB
D[あなたのドキュメント / コード] --> E[ローカル埋め込みモデル]
E --> V[(Chroma ベクターデータベース - ディスク上)]
Q[エージェントクエリ] --> QE[クエリをローカルで埋め込む]
QE --> V
V -->|上位kチャンク| A[Qwen エージェント]
A --> Ans[根拠のある回答]
これはレッスン5で学んだAgentic RAGパターンと同じですが、すべてのコンポーネントがマシン上で動いている点だけが異なります。
MCPは輸送層であってクラウドサービスではありません。MCPサーバーはstdio上でローカルプロセスとして動作し、標準プロトコルでエージェントにツールを提供します。これにより、ファイルシステムアクセス、git操作、データベースクエリなどMCPサーバーのエコシステムを完全にオフラインで再利用できます。
セキュリティ姿勢はクラウドとは異なりますが全く無いわけではありません。ローカルMCPサーバーはユーザーの権限で動作するため、アクセス範囲をプロジェクトディレクトリに限定し(ホームフォルダ全体でなく)、出力は入力として検証するよう扱うべきです。
ローカルファーストはローカルオンリーではありません。成熟したシステムは機微性や難易度に応じてルーティングを行います:
| 状況 | 実行場所 |
|---|---|
| 機微なコード・データ、またはオフライン時 | ローカルSLM |
| 単純で範囲限定なタスク | ローカルSLM(安くて速い) |
| 非機微データの難しい複数ホップ推論 | クラウドモデル |
| 停電などの全状況 | ローカルSLM(劣化しながらも動作) |
これはレッスン16のモデルルーティングの考え方と同様で、唯一違うのは「モデル」の一つが自分のマシンになったことです。堅牢な設計ではクラウド不可時にローカルにフォールバックし、エージェントは完全に停止せず品質低下で済みます。
flowchart LR
Q[リクエスト] --> S{センシティブまたはオフラインですか?}
S -->|はい| L[ローカルSLM]
S -->|いいえ| C{深い推論が必要ですか?}
C -->|いいえ| L
C -->|はい| Cloud[クラウドモデル]
L --> Out[レスポンス]
Cloud --> Out
code_samples/17-local-agent-foundry-local.ipynb を開いて順に進めてください。以下が完全にワークステーション上で動作するローカルエンジニアリングアシスタントとして構築されます:
どの時点でもクラウド推論は使いません。
アシスタントはOpenAI互換エンドポイントを介してFoundry Localに接続するため、コードはクラウドレッスンとほぼ同様で、クライアントだけが異なります:
from foundry_local import FoundryLocalManager
from openai import OpenAI
# Foundry Localはモデルを検出してダウンロードし、ローカルのエンドポイントを提供します。
manager = FoundryLocalManager(\"qwen2.5-7b-instruct\")
client = OpenAI(base_url=manager.endpoint, api_key=manager.api_key) # api_keyはローカルのプレースホルダーです
ツールは一般的なPython関数で、プロジェクトディレクトリ内に限定されています:
def read_file(path: str) -> str:
\"\"\"Read a file, but only inside the sandboxed project directory.\"\"\"
full = (PROJECT_ROOT / path).resolve()
if PROJECT_ROOT not in full.parents and full != PROJECT_ROOT:
return \"Access denied: path is outside the project directory.\"
return full.read_text(encoding=\"utf-8\")
サンドボックスチェックに注意してください — ローカルでも任意パスを読むツールはリスクが高いため、ノートブックではすべてのツールが単一プロジェクトルートにスコープされています。
課題に進む前に理解度を試しましょう。
1. エージェントをクラウドでなくローカルで動かす具体的な理由を2つ挙げてください。
2. ローカルエージェントにおけるSLMとツールの役割分担は何で、なぜそうするのですか?
3. Foundry Localでクラウドエージェントのコードを再利用可能にしている仕組みは?
4. 何故任意のSLMでなくQwen関数呼び出しモデルを使うのですか?
5. ローカルRAGパイプラインでマシン上で動作するコンポーネントはどれですか?
6. ローカルMCPサーバーはマシン上で動作します。それだけで自動的に安全でしょうか?どんな注意が必要ですか?
7. ローカルモデルを含む合理的なハイブリッドルーティングルールを説明してください。
8. 今回のローカルエージェント実行に現実的な最低RAMはどれくらいで、多いと何が得られますか?
ローカルエンジニアリングアシスタントを拡張し、あなたが選んだ小規模プロジェクトのローカルドキュメントレビュアーを作ってください(もしよければこのレポジトリのレッスンフォルダを使って構いません)。
提出物には以下を含めてください:
プロジェクト内のTODO/FIXMEコメントをスキャンし、ファイル名と行番号付きで返すfind_todosツールを追加。read_fileと同様のサンドボックスチェックを保持してください。
その後、このレビュアーに対してクラウドに移すものとローカルに残すものについて短い段落を書き、理由を述べてください。ローカルコンポーネントが正しく連携されているか、ハイブリッド推論が妥当かどうかで評価されます。モデルの品質に関しては評価されません。
このレッスンでは、あなた自身のマシン上だけで動作するエージェントを構築しました:
これで展開の軌跡が完成しました:レッスン16ではエージェントをMicrosoft Foundryにスケールアップし、このレッスンでは単一ワークステーションにスケールダウンしました。次のレッスンは展開済みエージェントのセキュリティを扱います。
免責事項: 本書類は AI 翻訳サービス Co-op Translator を使用して翻訳されています。正確性を期していますが、自動翻訳には誤りや不正確な部分が含まれる可能性があることをご承知おきください。原文の原語版が正式な情報源とみなされるべきです。重要な情報については、専門の人間による翻訳を推奨します。本翻訳の利用により生じたいかなる誤解や解釈違いについても、当方は責任を負いかねます。