Skip to content
  • Home
  • Code
  • iOS & Swift
  • Combine
  • RxSwift
  • SwiftUI
  • Flutter & Dart
  • Tutorials
  • Art
  • Blog
Fx Studio
  • Home
  • Code
  • iOS & Swift
  • Combine
  • RxSwift
  • SwiftUI
  • Flutter & Dart
  • Tutorials
  • Art
  • Blog
Foundation Models
Written by chuotfx on June 25, 2026

Foundation Models và “Hello World” trong 10 phút

iOS & Swift

Contents

  • Chuẩn bị
  • Hello World này chứng minh cái gì?
  • Foundation Models là gì?
  • Cách nhanh nhất để thử: ba dòng trong #Playground
  • Chỗ nào là “AI” trong code?
  • Chỗ nào là “on-device”?
  • Một cái bẫy: “dùng Foundation Models” không bằng “on-device”
  • Tạo project SwiftUI tối giản
  • File 1: AIFeatureGate.swift
  • File 2: FoundationModelsHelloView.swift
  • Cách demo cho người xem
  • Tại sao phải có fallback?
  • Hello World này chưa chứng minh gì?
  • Prompt cho agent nếu muốn để Claude / Codex tạo demo
  • Tạm kết

Chào mừng bạn đến với Fx Studio. Bài này mở màn cho mạch Agentic Coding for iOS, nơi mình lục lại nghề iOS bằng một con đường hơi ngược đời: để AI agent phụ dựng lại workspace, rồi dùng chính workspace đó để build các tính năng AI on-device của Apple.

Nghe hơi vòng. Nhưng bắt đầu thì không nên vòng. Bài đầu tiên về Foundation Models chỉ cần làm một việc rất nhỏ: gọi model chào lại mình.

Không EventKit. Không @Generable. Không tool calling. Không scan poster. Chưa cần làm gì nghe to tát cả.

Ta chỉ cần trả lời 2 câu:

  • Dòng code nào gọi AI?
  • Dòng nào cho thấy AI đó chạy trên device?

Bắt đầu thôi!

Chuẩn bị

Bài này nhẹ, không cần nhiều nền. Để chạy được demo này, bạn cần vài thứ cơ bản:

  • Mac Apple Silicon.
  • Xcode beta có SDK hỗ trợ FoundationModels.
  • Một iPhone / iPad / Mac hỗ trợ Apple Intelligence và Foundation Models.
  • Project SwiftUI tối giản.
  • Chạy trên device thật nếu muốn chứng minh phần on-device cho đàng hoàng.

Lưu ý nhỏ: simulator không phải chỗ tốt để demo Foundation Models. Với bài này, mình xem device thật là bắt buộc.

Với lại, vì đây là API mới, trước khi copy code đi publish hoặc đem demo trước đám đông, bạn nên verify lại bằng Xcode autocomplete hoặc ExecuteSnippet. Đừng tin trí nhớ của agent. Đừng tin cả trí nhớ của mình.

Mình già rồi, mình biết.

Hello World này chứng minh cái gì?

Một demo nhỏ để trả lời câu hỏi rất căn bản: app iOS gọi AI ở dòng nào, và vì sao ta nói nó chạy on-device?

Một demo Hello World với Foundation Models nên chứng minh 4 chuyện:

  1. App import được FoundationModels.
  2. Runtime báo model có thể dùng được trên device hiện tại.
  3. App gửi một prompt ngắn vào LanguageModelSession.
  4. Khi tắt mạng, app vẫn nhận được response.

Chỉ vậy thôi.

Nhưng 4 dòng đó rất quan trọng. Vì nếu bỏ qua bước này, ta rất dễ nhảy thẳng vào mấy demo nhìn “wow” hơn, rồi đến lúc build fail lại không biết lỗi nằm ở đâu: framework chưa có, device không hỗ trợ, region chưa hỗ trợ, Apple Intelligence chưa bật, hay code mình gọi sai API.

Hello World là cái cọc đầu tiên đóng xuống đất.

Foundation Models là gì?

Nói ngắn gọn, Foundation Models framework là cách Apple cho app của mình gọi model thuộc Apple Intelligence ngay trong code Swift. Apple ra mắt nó ở WWDC 2025.

Với developer iOS, điểm thú vị nằm ở chỗ: ta không bắt đầu bằng API key, endpoint, request JSON, token pricing. Ta bắt đầu bằng framework hệ thống:

import FoundationModels

Sau đó gọi model thông qua API Swift, ví dụ như LanguageModelSession.

Ở góc nhìn app, nó giống một capability của hệ điều hành hơn là một web service bên ngoài.

Nói vậy không có nghĩa là ta khỏi cần kiểm tra gì. Ngược lại, vì nó phụ thuộc device, OS, region và trạng thái Apple Intelligence, ta càng phải gate kỹ.

Cách nhanh nhất để thử: ba dòng trong #Playground

Trước khi dựng cả app, có một cách thử nhẹ hơn nhiều. Dùng macro #Playground ngay trong Xcode, chạy thẳng trong canvas, thấy output liền:

import Playgrounds
import FoundationModels

#Playground {
    let session = LanguageModelSession()
    let response = try await session.respond(to: "Chào! Bạn là model gì?")
    print(response.content)
}

Ba dòng cốt lõi. Tạo LanguageModelSession, gọi respond(to:), đọc response.content. Không endpoint, không key, không network.

Chạy được tới đây là bạn đã có hello world đúng nghĩa. Phần còn lại của bài chỉ là nâng nó lên một màn hình SwiftUI thật, để demo trước người khác cho rõ ràng.

Chỗ nào là “AI” trong code?

Trong Hello World này, phần gọi AI nằm ở đoạn tạo session và gửi prompt.

Ví dụ:

let session = LanguageModelSession(
    instructions: "You are a concise assistant for an iOS demo."
)

let response = try await session.respond(
    to: "Say hello to an iOS developer returning to Swift. Keep it under 20 words."
)

output = response.content

Ta có 3 thứ cần nhìn:

  • LanguageModelSession: phiên làm việc với model.
  • respond(to:): gửi prompt vào model.
  • response.content: phần text model sinh ra.

Nếu viết app cloud AI quen rồi, bạn có thể hình dung đoạn này tương đương với việc gọi một completion API. Nhưng thay vì tự tạo HTTP request tới server bên ngoài, app đang nói chuyện với model hệ thống thông qua framework của Apple.

Đây là dòng “gọi AI” của demo.

Không phải button. Không phải SwiftUI view. Không phải chữ “AI” trên màn hình.

Mà là đoạn session.respond(...).

Chỗ nào là “on-device”?

Phần on-device có 2 lớp.

Lớp thứ nhất là runtime check:

SystemLanguageModel.default.availability

Ta hỏi hệ thống: model mặc định có dùng được trên device này không?

Nếu có, app mới render tính năng AI. Nếu không, app hiện fallback.

Ví dụ mình gom lại thành một gate nhỏ:

import FoundationModels

enum AIFeatureGate {
    static var availability: SystemLanguageModel.Availability {
        SystemLanguageModel.default.availability
    }

    static var isAvailable: Bool {
        if case .available = availability {
            return true
        }

        return false
    }

    static var unavailableMessage: String {
        switch availability {
        case .available:
            return "Foundation Models is available."

        case .unavailable(let reason):
            return "Foundation Models is unavailable: \(reason)"

        @unknown default:
            return "Foundation Models availability is unknown on this SDK."
        }
    }
}

Đây là bằng chứng đầu tiên: app không giả vờ có AI. Nó hỏi runtime thật.

Lớp thứ hai là demo offline.

Khi app báo available, ta tắt Wi-Fi hoặc bật Airplane Mode, rồi bấm Run Hello. Nếu response vẫn sinh ra, ta có một bằng chứng trực quan rằng flow này không cần gọi cloud API bên ngoài.

Một cái bẫy: “dùng Foundation Models” không bằng “on-device”

Chỗ này mình tách riêng vì nó quan trọng, và vì nó là khác biệt giữa WWDC 2025 và WWDC 2026 – đừng để lẫn.

Ở WWDC 2025, Foundation Models là on-device thuần. Tới WWDC 2026, Apple nâng nó thành nền tảng hybrid: cùng một API có thể route xuống on-device, lên Private Cloud Compute, hoặc sang third-party như Claude, Gemini. Nghĩa là từ đây, “tôi dùng Foundation Models” không còn tự động đồng nghĩa với “chạy trên máy”.

Vậy khi nào chắc chắn on-device? Khi bạn gọi SystemLanguageModel.default. Đó là con model nằm trong máy.

Và đây là chỗ hay của phép thử tắt mạng: nó vừa chứng minh on-device, vừa loại trừ luôn khả năng nó lén route lên cloud. Nếu cái đang chạy là PCC hay third-party, mất mạng là fail. Nó sống sót qua airplane mode tức là nó thật sự local. Một phép thử, hai kết luận.

Nói cho chặt: demo này chứng minh đường gọi đang dùng Foundation Models local capability của hệ thống, không chứng minh mọi tính năng Apple Intelligence đều luôn chạy local trong mọi tình huống. Bài này chỉ nói về Hello World với SystemLanguageModel.default.

Nói vừa đủ thôi. Đỡ bị bắt bẻ.

Tạo project SwiftUI tối giản

Bạn tạo một SwiftUI app mới, ví dụ tên là:

FoundationModelsHello

Sau đó tạo cấu trúc đơn giản:

FoundationModelsHello/
├── Core/
│   └── AI/
│       └── AIFeatureGate.swift
│
└── Features/
    └── FoundationModelsHello/
        └── FoundationModelsHelloView.swift

Không cần architecture cầu kỳ. Demo nhỏ thì để nó nhỏ.

Cái bẫy của demo AI là mình hay muốn chứng minh quá nhiều thứ trong một lần. Rồi cuối cùng chứng minh được mỗi chuyện mình tham.

File 1: AIFeatureGate.swift

Tạo file: Core/AI/AIFeatureGate.swift

Nội dung:

import FoundationModels

/// Kiểm tra Foundation Models trước khi render hoặc gọi bất kỳ AI feature nào.
///
/// Purpose:
/// - Gom logic availability vào một chỗ để mọi feature AI dùng chung.
/// - Tránh crash hoặc UI chết cứng trên device / region chưa hỗ trợ.
///
/// Assumptions:
/// - Chạy trên SDK có FoundationModels framework.
/// - API availability có thể thay đổi theo SDK beta, nên cần verify lại bằng Xcode autocomplete.
enum AIFeatureGate {
    static var availability: SystemLanguageModel.Availability {
        SystemLanguageModel.default.availability
    }

    static var isAvailable: Bool {
        if case .available = availability {
            return true
        }

        return false
    }

    static var unavailableMessage: String {
        switch availability {
        case .available:
            return "Foundation Models is available."

        case .unavailable(let reason):
            return "Foundation Models is unavailable: \(reason)"

        @unknown default:
            return "Foundation Models availability is unknown on this SDK."
        }
    }
}

Nếu đoạn SystemLanguageModel.Availability hoặc case enum khác với SDK bạn đang dùng, đừng cố sửa bằng trí nhớ. Mở autocomplete lên và để Xcode nói sự thật.

Đây là thói quen nên có khi làm với API mới.

File 2: FoundationModelsHelloView.swift

Tạo file: Features/FoundationModelsHello/FoundationModelsHelloView.swift

Nội dung:

import SwiftUI
import FoundationModels

/// View Hello World tối thiểu cho Apple Foundation Models.
///
/// Purpose:
/// - Chứng minh app gọi được on-device language model.
/// - Hiển thị rõ trạng thái available / unavailable.
/// - Làm baseline trước khi chuyển sang @Generable hoặc tool calling.
///
/// Output:
/// - Một câu trả lời text ngắn từ model, hoặc fallback message nếu device không hỗ trợ.
///
/// Assumptions:
/// - Chạy trên device thật có Apple Intelligence / Foundation Models.
/// - API `LanguageModelSession.respond(to:)` cần verify lại theo SDK beta đang cài.
struct FoundationModelsHelloView: View {
    @State private var output = "Chưa chạy."
    @State private var isRunning = false

    var body: some View {
        VStack(alignment: .leading, spacing: 16) {
            Text("Foundation Models Hello")
                .font(.title.bold())

            Text(AIFeatureGate.isAvailable ? "Foundation Models: Available" : "Foundation Models: Unavailable")
                .font(.headline)

            runtimeBox

            Text(output)
                .frame(maxWidth: .infinity, alignment: .leading)
                .padding()
                .background(.thinMaterial)
                .clipShape(RoundedRectangle(cornerRadius: 12))

            Button {
                Task {
                    await runHello()
                }
            } label: {
                if isRunning {
                    ProgressView()
                } else {
                    Text("Run Hello")
                }
            }
            .buttonStyle(.borderedProminent)
            .disabled(isRunning || !AIFeatureGate.isAvailable)

            Spacer()
        }
        .padding()
        .onAppear {
            if !AIFeatureGate.isAvailable {
                output = AIFeatureGate.unavailableMessage
            }
        }
    }

    private var runtimeBox: some View {
        VStack(alignment: .leading, spacing: 6) {
            Text("Runtime")
                .font(.headline)

            Text("Framework: FoundationModels")
            Text("Model: SystemLanguageModel.default")
            Text("Call site: LanguageModelSession.respond(to:)")
            Text("Network test: turn Wi-Fi off before tapping Run Hello")
        }
        .font(.caption)
        .foregroundStyle(.secondary)
        .frame(maxWidth: .infinity, alignment: .leading)
        .padding()
        .background(.thinMaterial)
        .clipShape(RoundedRectangle(cornerRadius: 12))
    }

    /// Gửi một prompt rất nhỏ vào Foundation Models và hiển thị kết quả.
    ///
    /// Main logic:
    /// - Re-check availability trước khi gọi model.
    /// - Tạo session cục bộ.
    /// - Gọi prompt ngắn để giảm biến số khi demo.
    /// - Bắt lỗi và hiện ra UI thay vì crash.
    @MainActor
    private func runHello() async {
        guard AIFeatureGate.isAvailable else {
            output = AIFeatureGate.unavailableMessage
            return
        }

        isRunning = true
        defer { isRunning = false }

        do {
            let session = LanguageModelSession(
                instructions: "You are a concise assistant for an iOS demo."
            )

            let response = try await session.respond(
                to: "Say hello to an iOS developer returning to Swift. Keep it under 20 words."
            )

            output = response.content
        } catch {
            output = "Foundation Models error: \(error.localizedDescription)"
        }
    }
}

#Preview {
    FoundationModelsHelloView()
}

Gắn view này vào app:

import SwiftUI

@main
struct FoundationModelsHelloApp: App {
    var body: some Scene {
        WindowGroup {
            FoundationModelsHelloView()
        }
    }
}

Chạy lên là ta có màn hình Hello World.

Cách demo cho người xem

Flow demo nên đi chậm một chút.

Đầu tiên, mở app và chỉ dòng:

Foundation Models: Available

Nói:

Dòng này không phải mình hard-code. App đang hỏi SystemLanguageModel.default.availability để biết model hệ thống có dùng được trên device này không.

Sau đó chỉ box Runtime:

Framework: FoundationModels
Model: SystemLanguageModel.default
Call site: LanguageModelSession.respond(to:)
Network test: turn Wi-Fi off before tapping Run Hello

Tiếp theo, tắt Wi-Fi.

Rồi bấm Run Hello.

Nếu app trả về một câu kiểu:

Welcome back to Swift. Build something small, local, and useful.

thì ta nói:

Đây là response từ LanguageModelSession. Ở demo này không có API key, không có endpoint, không gọi ChatGPT hay Claude. App đang dùng Foundation Models qua framework hệ thống. Và vì mình vừa tắt mạng mà nó vẫn chạy, ta biết chắc nó không lén route lên cloud.

Vậy là đủ.

Không cần nói quá.

Foundation Models

Tại sao phải có fallback?

Vì Foundation Models không phải lúc nào cũng available.

Có nhiều lý do:

  • Device không hỗ trợ.
  • OS / SDK chưa đúng.
  • Region / account chưa hỗ trợ.
  • Apple Intelligence chưa bật.
  • Runtime trả về trạng thái unavailable vì lý do hệ thống.

Nếu mình viết thẳng:

let session = LanguageModelSession(...)

rồi assume mọi máy đều chạy, thì demo rất dễ chết.

Vì vậy, mọi AI feature nên có gate:

if AIFeatureGate.isAvailable {
    FoundationModelsHelloView()
} else {
    Text(AIFeatureGate.unavailableMessage)
}

Với app thật, fallback có thể là form nhập tay, rule-based parser, hoặc ẩn feature AI đi. Với Hello World, hiện message là đủ.

Graceful fallback không làm demo kém sang. Nó làm demo giống app thật hơn.

Hello World này chưa chứng minh gì?

Phần này nên nói rõ, vì nó giúp bài viết không bị hype.

Demo này chưa chứng minh:

  • model parse được structured data;
  • @Generable hoạt động ra sao;
  • guided generation có tốt hơn JSON parsing không;
  • tool calling hoạt động như thế nào;
  • app có thể tạo EKEvent;
  • workflow agentic trong Xcode có thể build feature từ spec.

Tất cả những thứ đó để bài sau.

Bài này chỉ chứng minh một đường dây tối thiểu:

SwiftUI button
    -> LanguageModelSession
    -> SystemLanguageModel
    -> response.content
    -> render ra UI

Và nếu tắt mạng mà đường dây đó vẫn chạy, ta đã có một Hello World đúng nghĩa cho AI on-device.

Prompt cho agent nếu muốn để Claude / Codex tạo demo

Nếu bạn đang dùng Claude Code hoặc Codex trong Xcode, có thể đưa prompt này:

Tạo demo Foundation Models Hello World tối thiểu.

Yêu cầu:
1. Tạo Core/AI/AIFeatureGate.swift để check SystemLanguageModel.default.availability.
2. Tạo Features/FoundationModelsHello/FoundationModelsHelloView.swift.
3. View có nút Run Hello, gọi LanguageModelSession với một prompt ngắn, hiển thị response.content.
4. Nếu model unavailable thì hiện fallback message, không crash.
5. Không đụng .pbxproj, signing, provisioning.
6. Sau khi viết code, dùng ExecuteSnippet hoặc autocomplete để verify API FoundationModels trên SDK hiện tại, rồi BuildProject.

Giữ code nhỏ, dễ đọc, demo được trên device thật.

Lưu ý dòng số 5.

Agent rất thích đụng vào chỗ không nên đụng. Với iOS project, .pbxproj, signing, provisioning là mấy vùng nên để người làm tay. Đừng để một bài Hello World biến thành buổi trừ tà code signing.

Tạm kết

Foundation Models Hello World không phải demo “wow”.

Nó chỉ bắt model chào mình.

Nhưng bài học nằm ở chỗ khác: ta thấy được đường dây từ SwiftUI vào LanguageModelSession, thấy runtime check qua SystemLanguageModel.default.availability, và thấy cách demo offline để chứng minh đây không phải một API cloud được bọc lại cho đẹp.

Tới đây, mình có cái nền đầu tiên:

  • Biết chỗ nào là dòng gọi AI;
  • Chỗ nào là check on-device capability;
  • Vì sao cần fallback;
  • Cách chứng minh demo vẫn chạy khi tắt mạng;
  • Nhớ phân biệt: chỉ SystemLanguageModel.default mới chắc chắn là on-device, vì sau 2026 cùng một framework có thể route lên cloud.

Ở bài tiếp theo, ta mới nâng cấp từ “model trả về một câu text” sang thứ có ích hơn: dùng @Generable để biến ngôn ngữ tự nhiên thành Swift struct.

Okay! Tới đây mình xin kết thúc bài Hello World đầu tiên với Apple Foundation Models. Nếu bạn đang thử trên máy thật và bị unavailable, cứ bình luận lại device / OS / region / Xcode version đang dùng, mình cùng soi tiếp nhóe.

Cảm ơn bạn đã đọc bài viết này!

FacebookTweetPinYummlyLinkedInPrintEmailShares0

Related Posts:

  • feature_bg_swift_10
    Swift Optional trong 10 phút
  • feature_bg_swift_04
    Automatic Reference Counting (ARC) trong 10 phút
  • feature_bg_3
    Clean Architecture trong iOS
  • feature_bg_swiftui_4
    Regular Expression (Regex) trong Swift
Tags: Agentic Coding for iOS, Apple Intelligence, Foundation Models, iOS, SwiftUI
Written by chuotfx

Hãy ngồi xuống, uống miếng bánh và ăn miếng trà. Chúng ta cùng nhau đàm đạo về đời, về code nhóe!

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Donate – Buy me a coffee!

Fan page

Fx Studio

Tags

Actor Advanced Swift AI AntiGravity api basic ios tutorial blog Charles Proxy ci/cd closure collectionview combine concurrency Context Engineering crashlytics dart dart basic dart tour Declarative delegate design pattern fastlane firebase flavor flutter GCD Google Stitch iOS MVVM optional Prompt engineering Prompt for Coding protocol Python rxswift Swift Swift 5.5 SwiftData SwiftUI SwiftUI Notes tableview testing TuiHocAI UI/UX unittest

Recent Posts

  • Foundation Models và “Hello World” trong 10 phút
  • Skill Boundary (P/L/R): dạy kỹ năng biết khi nào nên dừng
  • Context – Cung cấp ít hơn để đạt kết quả tốt hơn
  • Tui Học AI – Bài 3 – “Tôi hỏi AI” → “Tôi quản lý mọi thứ AI nhìn thấy”
  • Đừng xoá hàm này (phần 1)
  • Tui Học AI – Bài 2 – “Tôi ra lệnh cho AI” → “Tôi cộng tác với AI”
  • Context Rot – Vì sao cho mô hình thêm thông tin đôi khi làm kết quả tệ đi?
  • Giải mã tool poisoning – Vì sao con AI coding tool an toàn nhất cũng không tự bảo vệ bạn
  • Tui Học AI – Bài 1 – “AI trả lời tôi” → “Tôi kiểm soát câu trả lời”
  • Ý ĐỊNH trong PROMPT – Vì sao AI làm đúng Lời và sai Hồn

You may also like:

  • Phù thủy phiên dịch ý tưởng
    feature_bg_blog_005
  • Autoresizing Masks trong 10 phút
    cropped-feature_bg_3.jpg
  • Dependency Injection trong 10 phút
    feature_bg_swift_04
  • Builder Pattern trong 10 phút
    feature_bg_3
  • Regular Expression (Regex) trong Swift
    feature_bg_swiftui_4

Archives

  • June 2026 (12)
  • May 2026 (2)
  • April 2026 (5)
  • March 2026 (5)
  • February 2026 (1)
  • January 2026 (10)
  • December 2025 (1)
  • October 2025 (1)
  • September 2025 (4)
  • August 2025 (5)
  • July 2025 (10)
  • June 2025 (1)
  • May 2025 (2)
  • April 2025 (1)
  • March 2025 (8)
  • January 2025 (7)
  • December 2024 (4)
  • September 2024 (1)
  • July 2024 (1)
  • June 2024 (1)
  • May 2024 (4)
  • April 2024 (2)
  • March 2024 (5)
  • January 2024 (4)
  • February 2023 (1)
  • January 2023 (2)
  • November 2022 (2)
  • October 2022 (1)
  • September 2022 (5)
  • August 2022 (6)
  • July 2022 (7)
  • June 2022 (8)
  • May 2022 (5)
  • April 2022 (1)
  • March 2022 (3)
  • February 2022 (5)
  • January 2022 (4)
  • December 2021 (6)
  • November 2021 (8)
  • October 2021 (8)
  • September 2021 (8)
  • August 2021 (8)
  • July 2021 (9)
  • June 2021 (8)
  • May 2021 (7)
  • April 2021 (11)
  • March 2021 (12)
  • February 2021 (3)
  • January 2021 (3)
  • December 2020 (3)
  • November 2020 (9)
  • October 2020 (7)
  • September 2020 (17)
  • August 2020 (1)
  • July 2020 (3)
  • June 2020 (1)
  • May 2020 (2)
  • April 2020 (3)
  • March 2020 (20)
  • February 2020 (5)
  • January 2020 (2)
  • December 2019 (12)
  • November 2019 (12)
  • October 2019 (19)
  • September 2019 (17)
  • August 2019 (10)

About me

Education, Mini Game, Digital Art & Life of coders
Contacts:
[email protected]

Fx Studio

  • Home
  • About me
  • Contact us
  • Mail
  • Privacy Policy
  • Donate
  • Sitemap

Categories

  • Art (1)
  • Blog (95)
  • Code (11)
  • Combine (22)
  • Flutter & Dart (24)
  • iOS & Swift (105)
  • RxSwift (37)
  • SwiftUI (80)
  • Tutorials (111)

Newsletter

Stay up to date with our latest news and posts.
Loading

    Copyright © 2026 Fx Studio - All rights reserved.