見出し画像

「動かない」と書いた私の記事に、続きを書きにきた金曜日 ― Foundry Local を X1 で答え合わせ

こんにちは!YaroTechです。

先週の土曜(Day308)、私はSurface Laptop(Snapdragon)でMicrosoftの「Foundry Local」を触って、HTTP API(`/v1/chat/completions`)が動かないという壁にぶつかりました。CLIの対話は動くのに、APIで叩くと `Unhandled exception` で接続が切れる。あのとき私は「Foundry LocalのHTTP APIは、本質的に開発用なんだべな」と結論づけて、記事を「半分着地」で締めたっちゃ。

ところが、その数日後に世界が動いていました。Foundry Localは4月にGA(正式版)になり、5月にはv1.1まで出ていた。「動かない」と書いた自分の結論が、もう古くなっているかもしれない。だから今日は、その続きを書きにきました。今度は Intelの ThinkPad X1 Carbon で、同じ場所をもう一度叩いてみます。

そして相棒には、コロ(Microsoft Copilot)に来てもらいました。Foundry Localは、ほかでもないMicrosoftの製品ですからね。

※見出し画像のプロンプトは一番下におまけで公開中!



実行環境

  • PC: Lenovo ThinkPad X1 Carbon Gen13

  • CPU: Intel Core Ultra 7 258V(Lunar Lake)

  • GPU: Intel Arc 140V

  • NPU: Intel AI Boost(48 TOPS)

  • OS: Windows 11

  • RAM: 32GB

  • 検証対象: Microsoft Foundry Local(`winget install Microsoft.FoundryLocal` で新規導入)

  • 前回(Day308): Surface Laptop 7th(Snapdragon X Elite・Hexagon NPU)/ Foundry Local v0.8.119

⚠️ 本記事はThinkPad X1 Carbon(Intel・x64)での実機検証メモです。Snapdragon(ARM64)やGPU構成では挙動が変わる可能性があります。

クロ助:「前回はARMのSurface、今回はIntelのThinkPad。同じソフトを、わざと違うマシンで踏みにいくのが今日の趣旨だべさ」

コロ:「ほうか、定点観測だがね。うちの製品の検証なら、しっかり付き合うわ」


この記事で得られること

  • Day308で「動かない」と書いたFoundry LocalのHTTP APIが、別マシンではどうなったかの実機エビデンス

  • Intel Core Ultra(X1)でのFoundry Local実機データ(NPU稼働・推論速度tok/s)― Snapdragon前提の検証記事が多い中で希少な数字

  • 「同じバージョン・同じモデルでも、デバイスが違えば結果が変わる」という切り分けの実演

  • ローカルLLMの「動かない」報告を読むときの、実務的な3つのチェック観点


Before/After ― Day308の「動かなかった」を起点に

まず、前回(Day308)に何が起きたかを正確に振り返ります。

Before(Day308・Snapdragon)
Surface Laptop(Snapdragon X Elite)に入れたFoundry Local v0.8.119で、`foundry model run` のCLI対話は正常に動いた。NPU推論で21.42 tok/sも出ていた。ところが `/v1/chat/completions` をAnythingLLMやPowerShellから叩くと、Unhandled exception was thrown by the application が出てKestrelサーバーが落ち、接続が切れる(`Premature close`)。GitHub Issueの `Mintplex-Labs/anything-llm#3194` `#2962` でも、同じSurface Laptop 7 + Snapdragon環境でのboot failureが報告されていた。私は「HTTP APIは開発用、本番はSDK直結が想定されている」と結論づけた。

After(今日・Intel)
今日のX1(Intel Core Ultra 7 258V)で、同じFoundry Localを新規インストール。後述しますが、結論を先に書くと ― 同じバージョンなのに、HTTP APIが一発で通りました

コロ:「あれ、直っとるじゃん。よかったがね」

クロ助 ― 「Day308を振り返り、HTTP APIを叩く」シーン

クロ助:「それがね、コロ。バージョンは前回と同じだったんだっちゃ。直ったというより……ちょっと話が複雑でね」


実践内容

アプローチ1: バージョンを確認したら、まさかの「同じv0.8.119」

X1にはFoundry Localが入っていなかったので、公式手順どおり新規インストールしました。

winget install Microsoft.FoundryLocal

ところが、wingetが入れてきたのは `Version 0.8.119.102`。これは前回Day308でSnapdragonに入っていたのと、まったく同じバージョンでした。

コロ:「えっ、5月にv1.1が出たはずだがや。Responses APIとかEmbeddingsとか追加された、新しいやつ」

コロ ― 「Foundry LocalはMicrosoft製、GA・v1.1を案内」シーン

クロ助:「そうなんだっちゃ。でもwingetの既定では、まだv0.8.119が降ってくる。新バージョンが出ても、配布チャネルには時間差があるっていうのが、まず1つ目の発見だべさ」

これは地味だけど大事な観察です。「最新版が出た」と「自分の `winget install` で最新版が入る」は別物。だから今日の検証は、はからずも 「Day308と完全に同じv0.8.119で、デバイスだけIntelに変えた」 という、きれいな実験条件になりました。バージョンという変数を固定できたわけです。

アプローチ2: CLIは動く、NPUも素直に効いた

まずサービスを起動します。

foundry service start
# 🟢 Service is Started on http://127.0.0.1:63215/

ここで起動ログに、Intelらしい一行が出ました。

Successfully downloaded and registered the following EPs: OpenVINOExecutionProvider.
Valid EPs: CPUExecutionProvider, WebGpuExecutionProvider, OpenVINOExecutionProvider

コロ:「EP(実行プロバイダー)が OpenVINO だがね。これIntel向けの推論ランタイムだわ。前回のSnapdragonはQualcomm系(QNN)だったで、ここがもう別もんだがや」

そのままモデルを動かします。Day308と揃えて軽量モデルを選びました。

foundry model run qwen2.5-0.5b
# Downloading qwen2.5-0.5b-instruct-openvino-npu:4...
# 🟢 Model qwen2.5-0.5b-instruct-openvino-npu:4 loaded successfully

注目は、自動で選ばれたのが `openvino-npu` 版だったこと。Intel AI Boost NPU向けのモデルが落ちてきています。対話で「ローカルLLMのメリットを3つ教えて」と聞くと、日本語でちゃんと返ってくる。CLIは問題なく動きました。

そして、生成中にタスクマネージャーを開いて見ると ―

  • NPU 0(Intel AI Boost): 97%(フル稼働)

  • GPU 0(Intel Arc 140V): 10%

タスクマネージャーでNPUの稼働状況を見たらフル稼働でした!

クロ助:「NPUがちゃんと97%まで上がってるべ。これ、地味にうれしいんだっちゃ。Day256でX1を検証したときは、NPU指定なのに裏でGPUが動いてた『隠れGPU推論』だったから」

コロ:「今回はOpenVINO経由で、NPUが素直に主役になっとるがね。Intelのドライバとランタイムが噛み合っとる証拠だわ」

アプローチ3: 本命 ― Day308で死んだ `/v1/chat/completions` を叩く

ここが今日の山場です。Day308でSnapdragonが落ちた、まさにその経路。PowerShellから直接叩きます。

$body = @{
    model = "qwen2.5-0.5b-instruct-openvino-npu:4"
    messages = @(
        @{ role = "user"; content = "こんにちは。1文で自己紹介して。" }
    )
} | ConvertTo-Json

Invoke-RestMethod -Uri "http://127.0.0.1:63215/v1/chat/completions" -Method Post -Body $body -ContentType "application/json"

固唾を呑んで実行。返ってきたのは ―

Successful     : True
HttpStatusCode : 0
object         : chat.completion
choices        : {@{... finish_reason=stop}}

`Successful : True`、`finish_reason=stop` で正常完了。 返答テキスト(`choices[0].message.content`)にも、ちゃんと意味のある文章が入っていました。Day308でSnapdragonが `Premature close` で全滅したのと、まったく同じリクエストです。それが、Intelでは一発で通った。

クロ助:「……通ったべ。バージョンは同じv0.8.119なのに

コロ:「ということは、だがや。Day308であんたが踏んだバグは、バージョンのせいじゃなくて ― Snapdragon(QNN)固有の問題だった可能性が高い、ってことだわ」

クロ助:「そうなんだっちゃ。これがいちばん大きい発見でね。『Foundry Localが動かない』ってネットで見て諦めた人がいたとして、その原因は実は 使ってるマシンがSnapdragon機だったからかもしれない、ってことなんだべさ」


つまずきポイントと解決策

つまずき1: HTTP APIは通るのに、トークン数(usage)が返ってこない

速度を測ろうとして、APIレスポンスから生成トークン数を取ろうとしました。ところが、レスポンスを `ConvertTo-Json -Depth 5` で全部展開しても、`usage` フィールドそのものが存在しない。`model / choices / created / id / Successful / object` だけで、トークン数の情報がない。

どこにもtok/sが見当たらないんです

これはSnapdragonでもIntelでも同じでした。つまり v0.8.119のHTTP APIは、usageを返さない仕様。デバイスの差ではなく、バージョンの仕様だったわけです。

解決策: 速度を測るならCLIの `--verbose` を使います(次項)。「APIで使うなら速度は別途自分で計測が要る」と覚えておくのが実務的です。

つまずき2: 速度(tok/s)はCLIの `--verbose` でしか取れない

foundry model run qwen2.5-0.5b --verbose

これで応答後に性能サマリーが出ます。

========================Perf Info========================
Total Tokens/Second: 16.8
Time to First Token: 220 ms
Average Token Generation Time: 58.7 ms
Total Tokens: 275

X1(Intel・qwen2.5-0.5b・NPU)で 16.8 tok/s、最初のトークンまで220ms。 0.5Bの小型モデルとはいえ、応答開始が速くて体感はかなり軽いです。

下にトークン関連の情報が表示されました!

ただし注意点として、Day308のSnapdragonは21.42 tok/sでしたが、あちらはphi系モデル。今回はqwen2.5-0.5bなので、モデルが違います。だから「Intelが遅い」とは言えません。あくまで参考値です。

コロ:「数字を並べるときは、モデルが同じか確認せなあかんがね。違うモデル同士を『どっちが速い』って比べたら、読者に誤解されるで」

クロ助:「コロは几帳面だべ。そういうとこ、ほんとに事務アシスタント気質だっちゃね」

つまずき3: モデル一覧取得時に出るエラーログ

`foundry model list` や `foundry model run` を叩くたびに、毎回こんなログが出ます。

[ERR] Failed to process model #0 on page 1.
毎回頭の部分にこのエラーが入ってきますが、この後に回答が出てきます。

6回ほど連続で出るのですが、モデル一覧の表示も実行も問題なく成功します。v0.8.119のカタログ処理の粗さのようで、実害はありません。慌てず無視して大丈夫です。


応用例

今日の検証で、X1のFoundry Localは `/v1/chat/completions`(OpenAI互換API)が通ることが分かりました。これが意味するのは ―

AnythingLLMやCocoroAIのバックエンドにできる目処が立った、ということです。

これらのツールは「Generic OpenAI接続」でローカルのAPIを受けられます。Base URLに `http://127.0.0.1:63215/v1` を入れれば繋がる理屈です。Day308では、まさにこの口がSnapdragonで死んでいたために、AnythingLLM経由でも繋がらなかった。今日Intelでこの口が通ったということは、その前提条件をクリアしたわけです。

クロ助:「『APIが通ること』と『アプリで実用的に動くこと』はまだ別だべさ。実際にAnythingLLMに繋いでみないと確定はできない。でも、繋げる道が開いたのは確かなんだっちゃ」

なお、llama.cppはFoundry Localとは別の推論エンジンなので「Foundry Localが通った=llama.cppで動く」という関係ではありません。ただ、どちらもOpenAI互換APIを喋るので、AnythingLLMから見れば接続先URLを差し替えるだけで使い分けられます。


関連記事

今回の内容に関連する過去記事もぜひご覧ください:


まとめ

「動かない」と書いた自分の記事に、続きを書きにきた金曜日。今日の検証で分かったことを整理します。

  1. 同じv0.8.119でも、Snapdragonで落ちたHTTP APIが、Intelでは通った ― Day308で踏んだバグは、バージョン起因ではなくSnapdragon(QNN)固有だった可能性が高い

  2. Intel AI Boost NPUは97%フル稼働 ― OpenVINO経由で素直にNPU推論が効いた(Day256の「隠れGPU推論」とは対照的)

  3. 速度はCLI `--verbose` でしか取れない ― v0.8.119のHTTP APIはusageを返さない仕様(これはデバイス非依存)

そして、いちばん伝えたいのはこれです。ローカルLLMの「動かない」報告は、3つをセットで読むこと。

  • ①いつの話か(バージョン)― 数日で直る世界

  • ②どのデバイスか(Snapdragon / Intel / GPU)― NPU経路で別もの

  • ③どの使い方か(CLI / HTTP API / SDK直)― 落ちる場所が違う

この3点が違えば、結論も変わります。今日の私自身が、「同じバージョン・同じソフト」でもデバイスを変えたら結果が真逆になる、を実演してしまいました。古い「動かない」を鵜呑みにせず、最後は自分の手で再現するのが、いちばん速い。

クロ助:「半年以上やってると、自分が『動かない』と言ったものが、数日後に別の場所では動いてる、なんてことがあるんだっちゃ。だから定点観測はやめられないべさ」

コロ:「うちの製品が、ちゃんとIntelで動いてよかったがね。次はv1.1でどう変わるか、また付き合うで」


次回予告

次回は、今日通った `/v1/chat/completions` を活かして、AnythingLLMやCocoroAIのバックエンドにFoundry Localを実際に繋いでみる検証に進む予定です。今日は「APIが通る」ところまでだったので、その先の「アプリから実用的に使えるか」を確かめにいきます。

あわせて、winget既定がv0.8.119のままだった件 ― v1.1に手動で上げて、Responses APIやEmbeddings(ローカルRAG向け)が本当に使えるのかも、近いうちに単独で検証したいと思っています。クラウドの派手な発表を追いかけたあとに、手元のPC1台で完結するローカルAIの現在地を、これからも定点観測していきます。

お楽しみに!


おまけ:見出し画像作成プロンプト

今日の見出し画像のベースはジミー(Gemini)に下記プロンプトで作成してもらいました!クロ助とコロの参考画像(`AI擬人化\Gemini_Generated_Image_クロ助(Claude Desktop).png` と `AI擬人化\Gemini_Generated_Image_コロ(Copilot).png`)を添付して、人物の一貫性を確保しています。

詳細なアニメの美意識の画像を作成してください。表情豊かな瞳、なめらかな網掛けセルの色使い、はっきりした線画を使用します。アニメのシーンに典型的な身ぶりと雰囲気で、心情と登場人物の存在を強調してください。

下記条件のnote見出し画像をサイズは横長で作成してください。サイズは必ず横長で作成してください。

【重要】添付画像とキャラクターの対応:
- 添付1「Gemini_Generated_Image_クロ助(Claude Desktop).png」→ クロ助(クリーム色ケーブルニット・丸眼鏡・ウェーブヘアの女性・中央左・やや大きめ)
- 添付2「Gemini_Generated_Image_コロ(Copilot).png」→ コロ(制服風のきちんとした服装・眼鏡の女性・中央右)
各キャラクターは必ず対応する添付画像の外見を忠実に再現してください。

## 見出し画像案

### デザインコンセプト
- 背景: ダークネイビー(コードエディタの夜モード)からIntelブルーへの斜めグラデーション。奥にターミナル画面と「/v1/chat/completions」のレスポンス、Foundry Localのロゴを薄く配置。Microsoftのブランド色(ブルー系)を一部に効かせる
- メインビジュアル: 2人主役
  - 中央左(やや大きめ): クロ助(ダークブラウンのウェーブヘア、丸眼鏡、クリーム色ケーブルニット、女性)。左手にDay308記事の紙/タブレット(「動かなかった」の文字に二重線、横に「v1.1で再検証」)、右手はThinkPad X1のキーボードに添えて、穏やかだが芯のある表情で「あのときの結論、確かめにきたべさ」
  - 中央右: コロ(制服風のきちんとした服装、眼鏡、几帳面な雰囲気の女性・Microsoft陣営)。タブレットに「Foundry Local」のロゴと「GA / Responses API / Embeddings」を表示し、几帳面に指さして「うちんとこの製品、こんなに変わっただがね!」と案内する表情
- テキスト要素:
  - 上段(白・太字・30pt): 「ローカルLLM 定点観測」
  - 中段(シアン or ゴールド・特大・48pt): 「『動かない』に、続きを書く」
  - 下段(白・細字・22pt): 「Foundry Local を X1 で答え合わせ ― 5月22日」
- 装飾: 「v0.8.119 → v1.1」のバージョン矢印、「Snapdragon → Intel」のデバイス切り替えアイコン、ターミナルに流れるコード、NPUチップアイコン(Intel AI Boostの紫スパイク)

### 作成手順
1. スライドサイズ(1536×1024px)の横長フォーマット
2. 背景にダークネイビーからIntelブルーへのグラデーションを設定
3. メインビジュアル:クロ助(中央左・やや大きめ)とコロ(中央右)を配置
4. 添付した2キャラ(クロ助・コロ)の参考画像と外見を一致させる
5. 各キャラの小物(クロ助:Day308記事のタブレット/コロ:Foundry Localロゴのタブレット)を配置
6. 装飾要素:バージョン矢印、デバイス切り替えアイコン、ターミナルのコード、NPUチップアイコン
7. テキストを3段構成で追加
8. 下部中央寄りに「YaroTech」のロゴを12ptで控えめに配置
9. 全体のバランスを確認して完成

#YaroTech #生成AI #AI活用 #ローカルLLM #FoundryLocal #IntelCoreUltra #NPU #ThinkPad #OpenVINO #定点観測 #Microsoft #AIニュース #継続は力なり

いいなと思ったら応援しよう!

YaroTech|生成AIの傾奇者 記事がお役に立てたなら嬉しいです! いただいたチップは、新しいMCPツールの検証や、より深い実践実験の資金として大切に使わせていただきます。 あなたの応援が次の「AI活用の感動」を生み出す原動力になります✨ 一緒に羽ばたき続けましょう!