【WWDC25】iPhoneだけでLLM⁉︎ Foundation Modelsを“3行”で動かしてみた

# TL;DR

- iPhoneの端末内で完結するLLM。**インターネットに接続不要** なため、どんな環境でも使用可能
- たった 3 行の Swift で、iPhone 15 Pro 以降（A17 Pro／M シリーズ）のみで 3B パラメータの言語モデルをオフライン推論
- 3行なので、とにかく簡単！！！
- ハマりポイントは 対応端末制限 と 初回ロードのキャッシュ。Tool Calling を絡めると簡易 RAG も可能

# Foundation Models 解説

| 用語 | 説明 |
|---------|--------|
| Foundation Models framework  | Apple Intelligence の オンデバイス LLM（約 3 B パラメータ） をアプリから直接呼び出せる新 API。端末内での推論が基本で、処理が重い場合だけクラウドへ自動フェイルオーバー。Swift のわずか数行で要約・リライト・抽出といった生成系タスクを実装できる。Xcode 26 β に「Foundation Models App」テンプレートも追加。 |
| FMTextModel      | Foundation Models の代表クラス。内部で A17 Pro／M1 以上の Neural Engine を使って推論してくれる。      | 
| Tool Calling      | モデルが 外部ツールや API を自律的に呼び出す 仕組み。RAG 的用途もできる。    | 
| Private Cloud Compute      | 端末性能を超えるタスクを処理する Apple 独自のセキュア推論クラウド。Apple Silicon サーバ上で大型モデルを動かし、エンドツーエンド暗号化＋コード署名でプライバシーを担保。 ログは残さず、第三者によるバイナリ検証を前提に設計されている。    | 

https://developer.apple.com/documentation/foundationmodels 
https://developer.apple.com/videos/play/wwdc2025/301/

# 環境セットアップ

※正直ここが時間かかります

以下リンクより、Xcode 26β版をインストールしてください。
https://developer.apple.com/news/releases/

iPhoneは設定>一般>ソフトウェアアップデート>ベータアップデート をオンにしてください。

# 実際にコード書いてみた

```swift 

import FoundationModels

              /// (略) ///

              // 3行でモデルを呼び出し
                    let model = SystemLanguageModel.default
                    let result = try await model.generate("Qiitaの記事の書くコツについて教えて")
                    output = result.string
```

これだけでモデルを呼び出すことができる。

SystemLanguageModelは、Apple Intelligence（約 3 B param のオンデバイス LLM）をアプリ側から触るためのシングルトンで、端末で 使えるか/使えないか を即判定し、LanguageModelSession へ橋渡ししてくれるものです。

### 動くチャットアプリのようなを作ってみた

文字入力をして、実行を押せばApple Intelligence を使い推論し、結果を返してくれるだけのアプリです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3553613/c40d77e7-dd2a-4656-9a7d-b6e76839137b.png)


``` swift

import SwiftUI
import FoundationModels

struct ContentView: View {
    @State private var userInput = ""      // ① ユーザー入力
    @State private var output = ""         // ② モデルからの返答
    @State private var isLoading = false   // ③ 送信中フラグ
    private let session = LanguageModelSession()  // ④ セッションを一度だけ生成

    var body: some View {
        VStack(spacing: 12) {
            // 入力欄
            TextEditor(text: $userInput)
                .frame(height: 100)
                .overlay(RoundedRectangle(cornerRadius: 8).stroke(Color.gray.opacity(0.5)))
                .padding(.horizontal)

            // 送信ボタン
            Button(action: sendPrompt) {
                if isLoading {
                    ProgressView()
                } else {
                    Text("送信")
                        .bold()
                }
            }
            .disabled(isLoading || userInput.isEmpty)
            .padding()

            Divider()

            // 出力欄
            ScrollView {
                Text(output)
                    .padding()
            }
        }
        .padding(.top)
    }

    // MARK: - プロンプト送信処理
    private func sendPrompt() {
        Task {
            guard SystemLanguageModel.default.availability == .available else {
                output = "モデルが利用できません"
                return
            }
            isLoading = true
            do {
                let response = try await session.respond(to: userInput)
                output = response.content          // ← .content で文字列を取得
            } catch {
                output = "エラー：\(error.localizedDescription)"
            }
            isLoading = false
        }
    }
}

```

上記のように比較的容易な形で書くことができます。

## 今後の展開

RAGを実現したいので、Tool Callingも少し触る予定。
iPhone内部でネットワークなしの環境で完結できるので、使い道が多くあると考えられる。
特に社用携帯など社外に漏らせない情報などなどで、可能性がある。