2025 年 11 月に開催された Microsoft Ignite 2025 で Windows AI API の拡充が発表されました。
過去にもブラウザに内蔵された生成 AI を呼び出したり、ブラウザ上で DeepSeek-R1 を動かしたりした私としては色々試してみたいところだったのですが、重大な問題に直面しました。Windows AI API は Copilot+ PC が必要要件なのに、私の手元にはないのです。実際、AI Dev Gallery でも Copilot+ PC Required と言われてしまい、Windows AI API の機能を試すことはできませんでした。
せっかく手軽に試せそうだったのにと悲嘆にくれていたところ、同年 5 月に開催された Microsoft Build 2025 で発表された Foundry Local の存在を思い出したのです。というわけで、本記事は 2025 年、生成 AI を使ってみてどうだった?のキャンペーンに寄せ、Foundry Local をPowerShell 経由で使ってみた様子をご紹介するものです。
まず、Windows 上でローカル LLM を扱う Microsoft 提供の手段を比較してみます。
| 技術 | 特徴 | 実行環境 |
|---|---|---|
| Windows AI API | Copilot+ PC に組み込まれた AI 機能を手軽に利用できる API。Windows App SDK / WinRT を通じて C#、C++、Rust 等から使用可能。 | NPU |
| Foundry Local | Microsoft がホストする ONNX モデルや任意の ONNX モデルを Windows PC 上で実行する CLI ツール。OpenAI 互換の REST API と、それと連携する Python、JavaScript、C# 向け SDK を提供。1 | CPU、GPU、 NPU |
| Windows ML | 任意の ONNX モデルを Windows PC 上で実行するフレームワーク。Windows App SDK / WinRT を通じて C#、C++、Rust 等から使用可能。 | CPU、GPU、NPU |
この中で Copilot+ PC を持っていない私が今すぐ手軽に試せるのは、やはり Foundry Local になりそうですね。2
インストールは winget でサクッと終わります。
winget install Microsoft.FoundryLocalインストールが完了したら、利用可能なモデルを確認してみましょう。
foundry model ls🟢 Service is Started on http://127.0.0.1:57311/, PID 19816!
🕛 Downloading complete!...
Successfully downloaded and registered the following EPs: NvTensorRTRTXExecutionProvider, CUDAExecutionProvider.
Valid EPs: CPUExecutionProvider, WebGpuExecutionProvider, CUDAExecutionProvider
Alias Device Task File Size License Model ID
-----------------------------------------------------------------------------------------------
phi-4 GPU chat 8.37 GB MIT Phi-4-cuda-gpu:1
GPU chat 8.37 GB MIT Phi-4-generic-gpu:1
CPU chat 10.16 GB MIT Phi-4-generic-cpu:1
----------------------------------------------------------------------------------------------------------
...(後略)
私の環境では以下のモデルが利用可能でした。
- Phi
- phi-4: 14B
- phi-4-mini: 3.8B
- phi-4-mini-reasoning: 3.8B
- phi-3.5-mini: 3.8B
- phi-3-mini-128k: 3.8B
- phi-3-mini-4k: 3.8B
- Qwen
- qwen2.5: 0.5B, 1.5B, 7B, 14B
- qwen2.5-coder: 0.5B, 1.5B, 7B, 14B
- DeepSeek
- deepseek-r1: 7B, 14B
- Mistral
- mistral-7b-v0.2: 7B
- GPT-OSS
- gpt-oss-20b: 20B
GPU が利用可能な環境であれば、cuda 版のモデルが選択できます。今回は Phi-4-cuda-gpu:1 を使ってみることにしました。
まずは CLI の対話モードで動作を確認します。
foundry model run Phi-4-cuda-gpu:1モデルの初回実行時には自動でダウンロードが開始され、完了すると入力待ちとなります。
Downloading Phi-4-cuda-gpu:1...
[####################################] 100.00 % [Time remaining: about 0s] 6.9 MB/s
🕔 Loading model...
🟢 Model Phi-4-cuda-gpu:1 loaded successfully
Model Phi-4-cuda-gpu:1 was found in the local cache.
Interactive Chat. Enter /? or /help for help.
Press Ctrl+C to cancel generation. Type /exit to leave the chat.
Interactive mode, please enter your prompt
> こんにちはと鳴く犬、こんにチワワ
🧠 Thinking...
🤖 こんにちは!あなたのユーモラスな言及を楽しんでいます。「こんにちはと鳴く犬、こんにチワワ」は、チワワが「こんにちは」と言うときに、その愛らしい性格と特徴的な鳴き声を指しているようですね。チワワは、その小さなサイズと大きな性格で知られており、彼らの鳴き声はしばしば「ワンワン」というよりも「ワフワフ」という音に似ていると言われています。何か他に質問があれば、お気軽にどうぞ!
導入成功です!
ダウンロードしたモデルの保存先は CLI から確認できます。
foundry cache location💾 Cache directory path: C:\Users\<ユーザー名>\.foundry\cache\models
Phi-4-cuda-gpu:1 の場合、公称通り 8.37 GB ありました。
Foundry Local サービスは起動中 OpenAI API 互換のローカルサーバーを稼働しており、ステータスを確認するとポート番号が表示されます。
foundry service status🟢 Model management service is running on http://127.0.0.1:49587/openai/status
EP autoregistration status: Successfully downloaded and registered the following EPs: NvTensorRTRTXExecutionProvider, CUDAExecutionProvider.
Valid EPs: CPUExecutionProvider, WebGpuExecutionProvider, CUDAExecutionProvider
この例では http://127.0.0.1:52487 で待ち受けているようです。curl.exe でリクエストを投げ、レスポンスからメッセージ部分を取り出してみましょう。
curl.exe -s http://127.0.0.1:52487/v1/chat/completions -H "Content-Type: application/json" -d '{ "model": "Phi-4-cuda-gpu:1", "messages": [{"role": "user", "content": "こんにちはと鳴く犬、こんにチワワ"}] }' | ConvertFrom-Json | % { $_.choices[0].message.content }こんにちは!あなたのユーモラスな言及を楽しんでいます。「こんにちはと鳴く犬、こんにチワワ」は、チワワが「こんにちは」と言うときに、その愛らしい性格と特徴的な鳴き声を指しているようですね。チワワは、その小さなサイズと大きな性格で知られており、彼らの鳴き声はしばしば「ワンワン」というよりも「ワフワフ」という音に似ていると言われています。何か他に質問があれば、お気軽にどうぞ!
さきほどと同じプロンプトを送信したところ、全く同じ応答が返ってきています。あくまで挙動からの推測ですが、Foundry Local では Top K はデフォルトで 1 となっているようです。3 たとえば、"top_k" : 2 と指定してやると生成 AI らしい揺らぎを持った回答になります。
curl.exe -s http://127.0.0.1:49587/v1/chat/completions -H "Content-Type: application/json" -d '{ "model": "Phi-4-cuda-gpu:1", "top_k" : 2, "messages": [{"role": "user", "content": "こんにちはと鳴く犬、こんにチワワ"}] }' | ConvertFrom-Json | % { $_.choices[0].message.content こんにちは!このフレーズは、犬が「こんにちは」と言うときの可愛らしさを表現しているようですね。特にチワワのような小さくて愛らしい犬種は、鳴き声が特徴的で、人々を楽しませます。チワワの「こんにちは」は、その小さくてかわいらしい姿と相まって、多くの人に愛されています。犬との触れ合いは、心を和ませる素晴らしい体験ですね。
こんにちは、と鳴く犬は、その明るく元気な様子で、人々を温かく迎えます。特に、その声を特徴的な小さなチワワは、愛くるしい鳴き声で「こんにちわ」と挨拶するように聞こえます。この表現は、犬の愛らしさと、人間と動物との間の親しみやすい関係を象徴しているかもしれません。チワワのような犬は、そのサイズに反して、大きな個性と愛らしい性格を持ってお
REST API サーバーとして振る舞ってくれるなら、PowerShell からの呼び出しも容易に行えそうです。上記のように curl.exe の出力をパースしてもよいですし、curl = Invoke-WebRequest や Invoke-RestMethod を使用してもよいでしょう。
ただし、実用にあたってはいくつかの問題が考えられます。
-
Foundry Local のポート番号が起動ごとに変わる
- API を呼び出す前に
foundry service statusで現在の値を確認する必要があります。
PS C:\> foundry service start 🟢 Service is Started on http://127.0.0.1:58238/, PID 32984! PS C:\> foundry service stop 🔴 Service is stopped. PS C:\> foundry service start 🟢 Service is Started on http://127.0.0.1:58241/, PID 30968! - API を呼び出す前に
-
会話履歴を引き継ぐのが手間
- 前回の会話に追加で応答するには、リクエストの
messagesパラメータに会話履歴を含めておく必要があります。 - これを PowerShell ライクな手法で実現できれば、他のコマンドレットとスマートに連携できます。
- 前回の会話に追加で応答するには、リクエストの
自動でポート番号を特定しつつ、会話履歴をパイプラインで入出力できる関数があれば便利になるでしょう。というわけで、実際に作ってみました。
function Get-Completions {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, Position = 0)]
[string]$Message,
[Parameter(Mandatory = $false, ValueFromPipeline = $true)]
[System.Collections.ArrayList]$History,
[Parameter(Mandatory = $false)]
[string]$Model = "Phi-4-cuda-gpu:1",
[Parameter(Mandatory = $false)]
[Double]$Temperature = 0.8,
[Parameter(Mandatory = $false)]
[int]$TopK = 50,
[Parameter(Mandatory = $false)]
[Double]$TopP = 1,
[Parameter(Mandatory = $false)]
[int]$MaxCompletionTokens = 1000
)
# Foundry Local を見つける
$status = foundry service status 2>&1 | Out-String
if ($status -match "(http://127\.0\.0\.1:\d+)") {
$baseUrl = $Matches[1]
}
else {
Write-Error "Foundry Local サービスが見つかりませんでした。foundry service start でサービスを起動してください。"
return
}
$apiUrl = "$baseUrl/v1/chat/completions"
# 会話履歴の準備
if ($null -eq $History) {
$History = [System.Collections.ArrayList]::new()
}
$userMessage = @{
role = "user"
content = $Message
}
[void]$History.Add($userMessage)
# Foundry Local にリクエスト
$payload = @{
model = $Model
messages = $History
temperature = $Temperature
top_p = $TopP
top_k = $TopK
max_completion_tokens = $MaxCompletionTokens
} | ConvertTo-Json -Depth 10
try {
$result = Invoke-RestMethod -Uri $apiUrl -Method Post -ContentType "application/json; charset=utf-8" -Body $payload
$content = $result.choices[0].message.content
$assistantMessage = @{
role = "assistant"
content = $content
}
[void]$History.Add($assistantMessage)
return , $History
}
catch {
Write-Error "Foundry Local へのリクエスト中に例外が発生しました: $_"
}
}これで、PowerShell から手軽に Foundry Local を呼び出せるようになりました。
. .\FoundryLocal.ps1
Get-Completions "チワワを使ったダジャレを一言で" | % { $_[-1].content }チワワになったら、小柄な問題になっちゃう!
会話履歴をパイプラインで引き回せるので、続けてメッセージを送信できます。
Get-Completions "チワワを使ったダジャレを一言で" | Get-Completions "そのおもしろさを解説して" | % { $_ | % { "[$($_.role)] $($_.content)" } }[user] チワワを使ったダジャレを一言で
[assistant] チワワっていいですね、あっちゅう間にかわいさが伝わります!
[user] そのおもしろさを解説して
[assistant] 「チワワっていいですね、あっちゅう間にかわいさが伝わります!」というダジャレのおもしろさは、いくつかの要素によって生まれています。
...(後略)
他コマンドレットとの連携もスマートに可能です。
Get-EventLog System -EntryType Error -n 1 | % { Get-Completions "このエラーの解決策を簡潔に教えて: $($_.Source) - $($_.Message)" } | % { $_[-1].content }
エラー 0x80073d02 は、更新やプログラムをインストールできないことを示しており、通常はシステムファイルとの競合や権限の問題が原因です。この問題を解決するためには、以下のステップを実行してください:
### 解決策 1: 管理者として更新マネージャーを実行
1. **Windows Update Troubleshooter** を実行します:
- **設定** > **更新とセキュリティ** > **トラブルシューティング** に移動します。
- **Windows Update** トラブルシューティングを選択し、指示に従って実行します。
...(後略)
# Run AI models locally with the power of Microsoft's Azure AI technology.
Get-Clipboard | Out-String | % { Get-Completions "自然な日本語に翻訳して: $_" } | % { $_[-1].content }
マイクロソフトのAzure AIテクノロジーの力を使って、ローカルでAIモデルを実行してください。
Copilot+ PC がなくても、Foundry Local を使って Windows 環境で簡単にローカル LLM サーバーを立てることができました。実用的には Ollama が一般的ですので、あえて Foundry Local を選ぶケースは少ないでしょうが、上記コードは他の OpenAI API 互換サーバーでも大半を流用できるはずです。PowerShell と LLM の接続するケースの参考になれば幸いです。
- microsoft/Foundry-Local
- ローカルAIを使用するMicrosoft Foundry on Windows | Microsoft Learn
- Foundry Local REST API reference | Microsoft Learn
- Foundry Local でローカルAI推論をやってみる

