Foundation Models Framework คืออะไร — AI บนอุปกรณ์ที่เปลี่ยนเกมจริง ๆ
ถ้าคุณเป็นนักพัฒนา iOS ที่อยากใส่ AI ลงในแอปแต่ไม่อยากยุ่งกับ API key, ค่า cloud ที่พุ่งไม่หยุด หรือปัญหาเรื่อง privacy — ตอนนี้ Apple มีคำตอบให้แล้ว
ใน iOS 26 Apple ปล่อย Foundation Models framework ออกมา ซึ่งเปิดให้นักพัฒนาเข้าถึง Large Language Model (LLM) ขนาด ~3 พันล้านพารามิเตอร์ ตัวเดียวกับที่ขับเคลื่อน Apple Intelligence ได้โดยตรงจากโค้ด Swift เลย ทุกอย่างรันบนอุปกรณ์ (on-device) ทั้งหมด ไม่ต้องใช้ API key ไม่มีค่าใช้จ่าย cloud และไม่จำเป็นต้องต่อเน็ตด้วยซ้ำ
แล้วมันต่างจาก LLM บนคลาวด์อย่าง ChatGPT หรือ Claude ยังไง?
- ความเป็นส่วนตัวเต็มที่ — ข้อมูลไม่ออกจากอุปกรณ์เลยแม้แต่ byte เดียว
- ใช้งานออฟไลน์ได้ — ไม่ต้องมีเน็ตก็ใช้ได้
- ฟรีตลอดกาล — ไม่มีค่าใช้จ่าย ใช้ได้ไม่จำกัดจำนวนครั้ง
- Latency ต่ำมาก — ตอบสนองเร็วประมาณ ~0.6ms time-to-first-token บน iPhone 15 Pro (เร็วจนแทบไม่รู้สึกว่ารอ)
ในบทความนี้ผมจะพาคุณเรียนรู้การใช้งาน Foundation Models framework ตั้งแต่พื้นฐานสุด ๆ ไปจนถึงเทคนิคขั้นสูงอย่าง Tool Calling พร้อมโค้ดตัวอย่างที่ copy ไปใช้ในแอปจริงได้เลย
ข้อกำหนดและอุปกรณ์ที่รองรับ
ก่อนจะเริ่มเขียนโค้ด มาเช็คกันก่อนว่าต้องมีอะไรบ้าง
ฮาร์ดแวร์ที่รองรับ
- iPhone — iPhone 15 Pro ขึ้นไป (ชิป A17 Pro หรือใหม่กว่า)
- iPad — รุ่นที่ใช้ชิป M1 ขึ้นไป
- Mac — Apple Silicon M1 ขึ้นไป
- Vision Pro — รองรับ visionOS 26
ซอฟต์แวร์ที่ต้องมี
- iOS 26, iPadOS 26, macOS 26 หรือ visionOS 26 ขึ้นไป
- Xcode 26 พร้อม iOS 26 SDK
- ต้องเปิดใช้งาน Apple Intelligence ในการตั้งค่า
- ภาษาที่รองรับ (ณ ตอนนี้): อังกฤษ, ฝรั่งเศส, เยอรมัน, อิตาลี, โปรตุเกส (บราซิล), สเปน, จีน (ตัวย่อ), ญี่ปุ่น, เกาหลี
จุดสำคัญที่หลายคนพลาด: iPhone 15 รุ่นปกติ (ไม่ใช่ Pro) แม้จะรัน iOS 26 ได้ แต่ใช้ Foundation Models framework ไม่ได้นะครับ ดังนั้นคุณ ต้อง เตรียม fallback สำหรับอุปกรณ์ที่ไม่รองรับเสมอ อย่าลืมเด็ดขาด
เริ่มต้นกับ LanguageModelSession — หัวใจหลักของ Framework
LanguageModelSession คือ class หลักที่ใช้สื่อสารกับโมเดล AI บนอุปกรณ์ มันเก็บบริบทของการสนทนา (Transcript) ไว้ตลอด session ทำให้โมเดลจำบริบทก่อนหน้าได้ — คิดง่าย ๆ ว่าเหมือน chat session นั่นแหละ
การใช้งานเบื้องต้น
import FoundationModels
// สร้าง session แบบง่ายที่สุด
let session = LanguageModelSession()
// ส่งคำถามและรอคำตอบ
let response = try await session.respond(to: "แนะนำสูตรอาหารไทยง่าย ๆ หน่อย")
print(response.content) // ข้อความตอบกลับจากโมเดล
แค่ 3 บรรทัดก็ใช้ AI บนอุปกรณ์ได้แล้ว จริง ๆ นะ ง่ายขนาดนี้เลย
กำหนด System Instructions
คุณสามารถกำหนดบทบาทหรือพฤติกรรมของโมเดลด้วย instructions ได้ ซึ่งตรงนี้คล้ายกับ system prompt ที่เราคุ้นเคยจาก ChatGPT:
let session = LanguageModelSession(instructions: """
คุณเป็นผู้ช่วยด้านการทำอาหารไทย
ตอบคำถามเกี่ยวกับสูตรอาหาร วัตถุดิบ และเทคนิคการปรุง
ตอบเป็นภาษาไทยเสมอ
""")
let response = try await session.respond(to: "ผัดกะเพราทำยังไง?")
print(response.content)
โมเดลจะพิจารณา instructions ก่อนทุกครั้งที่ตอบ ผลลัพธ์เลยตรงกับบทบาทที่กำหนดไว้
Prewarm — โหลดโมเดลล่วงหน้าให้พร้อมใช้
ถ้าคุณรู้ล่วงหน้าว่าผู้ใช้จะเรียก AI เร็ว ๆ นี้ (เช่น ผู้ใช้กำลังพิมพ์ข้อความ) ควรเรียก prewarm() เพื่อโหลดโมเดลเข้า memory ไว้ก่อน จะได้ลด latency ตอนตอบครั้งแรก:
let session = LanguageModelSession()
try await session.prewarm() // โหลดโมเดลล่วงหน้า
// ตอนเรียก respond จะเร็วขึ้นมาก
let response = try await session.respond(to: "สวัสดี!")
เทคนิคเล็ก ๆ น้อย ๆ แบบนี้แหละที่ทำให้แอปรู้สึก smooth ขึ้นเยอะ
Streaming Response — แสดงคำตอบแบบเรียลไทม์ใน SwiftUI
การใช้ respond(to:) จะต้องรอให้โมเดลสร้างคำตอบเสร็จหมดก่อนถึงจะแสดงผลได้ สำหรับคำตอบยาว ๆ มันทำให้ UX ไม่ค่อยดีเท่าไหร่ ผู้ใช้จะรู้สึกว่าแอปค้าง
ทางแก้คือใช้ Streaming เพื่อแสดงข้อความทีละส่วนแบบเรียลไทม์ แบบเดียวกับที่ ChatGPT ทำนั่นแหละ
import SwiftUI
import FoundationModels
struct ChatView: View {
@State private var session = LanguageModelSession()
@State private var userInput = ""
@State private var output = ""
@State private var isLoading = false
var body: some View {
VStack(spacing: 16) {
ScrollView {
Text(output)
.frame(maxWidth: .infinity, alignment: .leading)
.padding()
}
HStack {
TextField("พิมพ์คำถาม...", text: $userInput)
.textFieldStyle(.roundedBorder)
.disabled(isLoading)
Button("ส่ง") {
Task { await sendMessage() }
}
.disabled(userInput.isEmpty || isLoading)
}
.padding(.horizontal)
}
}
func sendMessage() async {
isLoading = true
output = ""
let prompt = userInput
userInput = ""
do {
let stream = session.streamResponse(to: prompt)
for try await partial in stream {
output = partial.content
}
} catch {
output = "เกิดข้อผิดพลาด: \(error.localizedDescription)"
}
isLoading = false
}
}
โค้ดด้านบนสร้างแอปแชทที่แสดงคำตอบแบบเรียลไทม์ ผู้ใช้จะเห็นข้อความค่อย ๆ ปรากฏขึ้นทีละนิด ให้ความรู้สึกเหมือนโมเดลกำลัง "พิมพ์" อยู่
อ้อ อีกอย่างที่ดีคือ session มี property isResponding ช่วยเช็คสถานะว่าโมเดลกำลังประมวลผลอยู่ไหม เอาไว้ป้องกันไม่ให้ส่งคำถามซ้อนกัน
Guided Generation ด้วย @Generable — ฟีเจอร์ที่ผมชอบที่สุด
ส่วนตัวแล้ว นี่คือฟีเจอร์ที่ทรงพลังที่สุดของ Foundation Models framework เลย ปกติถ้าใช้ LLM ทั่วไป เราจะได้ข้อความธรรมดากลับมาแล้วต้องมานั่ง parse เอง (ซึ่งพังบ่อยมาก) แต่กับ @Generable คุณกำหนดให้โมเดลสร้างผลลัพธ์เป็น Swift struct ที่มี type-safety ได้โดยตรงเลย
@Generable คืออะไร
@Generable เป็น macro ที่บอก Foundation Models framework ว่า struct นี้สามารถถูกสร้างโดย AI ได้ ระบบจะสร้าง schema ตอน compile time แล้วบังคับให้โมเดลสร้างผลลัพธ์ตาม schema นั้น — มันเป็นการ constrain ระดับ token generation เลยนะ ไม่ใช่แค่หวังว่าจะได้ JSON ที่ถูกต้อง
import FoundationModels
@Generable
struct RecipeRecommendation {
let name: String
let ingredients: [String]
let steps: [String]
let cookingTimeMinutes: Int
let difficulty: String
}
// ใช้งาน
let session = LanguageModelSession()
let result = try await session.respond(
to: "แนะนำสูตรต้มยำกุ้ง",
generating: RecipeRecommendation.self
)
let recipe = result.content
print(recipe.name) // "ต้มยำกุ้งน้ำข้น"
print(recipe.ingredients) // ["กุ้ง", "เห็ดฟาง", ...]
print(recipe.cookingTimeMinutes) // 30
ไม่ต้อง parse JSON ไม่ต้อง decode เอง ได้ Swift struct กลับมาตรง ๆ สะอาดมาก
@Guide — บอกโมเดลให้ละเอียดขึ้น
macro @Guide ใช้กำกับ property แต่ละตัวเพื่อให้คำแนะนำเพิ่มเติมแก่โมเดล ช่วยให้ผลลัพธ์แม่นยำขึ้น:
@Generable
struct QuizQuestion {
@Guide(description: "คำถามที่ชัดเจนและเข้าใจง่าย")
let question: String
@Guide(description: "ตัวเลือกคำตอบ 4 ข้อ", .count(4))
let choices: [String]
@Guide(description: "ดัชนีของคำตอบที่ถูกต้อง (0-3)")
let correctIndex: Int
@Guide(description: "คำอธิบายสั้น ๆ ว่าทำไมคำตอบนั้นถูก")
let explanation: String
}
@Guide มีตัวเลือกหลายแบบที่น่าสนใจ:
description:— อธิบายให้โมเดลเข้าใจว่า property นี้ควรมีค่าแบบไหน.count(n)— กำหนดจำนวนสมาชิกของ array ตายตัว.anyOf([...])— จำกัดค่าที่เป็นไปได้ (ทำงานคล้าย ๆ enum)
ระวัง — ลำดับ Property สำคัญมาก
อันนี้เป็นกับดักที่นักพัฒนาหลายคนเจอ (รวมถึงผมด้วยตอนแรก) โมเดลจะสร้างค่าของ property ตามลำดับที่ประกาศในโค้ด ดังนั้นถ้า property ตัวหนึ่งต้องอ้างอิงค่าจากอีกตัว ต้องประกาศตัวที่ถูกอ้างอิงไว้ก่อน
@Generable
struct StudyPlan {
let subject: String // ✅ สร้างก่อน
let weeklyTopics: [String] // ✅ สร้างทีหลัง — อ้างอิง subject ได้
// ❌ ถ้าสลับลำดับ weeklyTopics จะไม่รู้ว่า subject คืออะไร
// เพราะโมเดลยังไม่ได้สร้างค่า subject
}
เหตุผลก็ตรงไปตรงมา LLM สร้างข้อมูลทีละ token — ถ้ายังไม่ได้สร้าง subject มันก็ไม่มีทางรู้ว่าจะใส่อะไรใน weeklyTopics จำไว้ง่าย ๆ: property ที่เป็น "input" ต้องมาก่อน property ที่เป็น "output"
Streaming กับ @Generable — Structured Output แบบเรียลไทม์
คุณใช้ streaming กับ @Generable struct ได้ด้วยนะ ระบบจะสร้าง type พิเศษชื่อ PartiallyGenerated ขึ้นมาอัตโนมัติ โดย property ทุกตัวจะเป็น optional — แล้วค่อย ๆ มีค่าเมื่อโมเดลสร้างเสร็จทีละส่วน
@Generable
struct TravelItinerary {
@Guide(description: "ชื่อทริปที่น่าสนใจ")
let tripName: String
@Guide(description: "คำอธิบายสั้น ๆ เกี่ยวกับทริป")
let description: String
@Guide(description: "แผนรายวัน", .count(3))
let dailyPlans: [String]
}
// Streaming structured output
let stream = session.streamResponse(
to: "วางแผนเที่ยวเชียงใหม่ 3 วัน",
generating: TravelItinerary.self
)
for try await partial in stream {
// partial.tripName อาจเป็น nil ตอนแรก แล้วค่อยมีค่า
if let name = partial.tripName {
print("ชื่อทริป: \(name)")
}
if let plans = partial.dailyPlans {
print("แผน: \(plans)")
}
}
// หรือรอผลลัพธ์สมบูรณ์ด้วย collect()
let finalResult = try await stream.collect()
print(finalResult.content.tripName) // ค่าสมบูรณ์ ไม่เป็น optional
เทคนิคนี้เหมาะมากสำหรับ UI ที่อยากแสดงข้อมูลทีละส่วน เช่น แสดงชื่อทริปก่อน แล้วค่อยแสดงแผนรายวันทีหลัง ผู้ใช้จะไม่รู้สึกว่าต้องรอนาน
Tool Calling — ให้โมเดลเรียกใช้โค้ด Swift ของคุณได้
โมเดล on-device มีขนาดแค่ ~3B parameter มันเลยไม่ได้ "รู้" ทุกอย่าง แต่สิ่งที่เจ๋งคือคุณขยายความสามารถของมันได้ด้วย Tool Calling — ให้โมเดลเรียกใช้ฟังก์ชัน Swift ของคุณเมื่อต้องการข้อมูลที่มันไม่มี
สร้าง Custom Tool
import FoundationModels
struct WeatherTool: Tool {
let name = "getWeather"
let description = "ดึงข้อมูลสภาพอากาศของเมืองที่ระบุ"
@Generable
struct Arguments {
@Guide(description: "ชื่อเมืองที่ต้องการดูสภาพอากาศ")
let city: String
}
func call(arguments: Arguments) async throws -> ToolOutput {
// ในแอปจริง จะเรียก Weather API ตรงนี้
let weatherData = await fetchWeather(for: arguments.city)
return ToolOutput(weatherData)
}
private func fetchWeather(for city: String) async -> String {
// จำลองการดึงข้อมูล
return "\(city): อุณหภูมิ 32°C, ท้องฟ้าแจ่มใส"
}
}
ใช้ Tool กับ Session
let session = LanguageModelSession(
instructions: "คุณเป็นผู้ช่วยวางแผนการเดินทาง",
tools: [WeatherTool()]
)
let response = try await session.respond(
to: "อากาศที่เชียงใหม่เป็นยังไงบ้าง?"
)
// โมเดลจะเรียก WeatherTool อัตโนมัติ แล้วนำผลลัพธ์มาตอบ
print(response.content)
ขั้นตอนที่เกิดขึ้นเบื้องหลังก็คือ เมื่อโมเดลตัดสินใจว่าต้องใช้ tool มันจะหยุดสร้างข้อความ → เรียก call(arguments:) ของ tool → รอผลลัพธ์ → แล้วนำมาประกอบคำตอบต่อ ทั้งหมดนี้เกิดขึ้นอัตโนมัติ คุณไม่ต้องจัดการอะไรเอง
GenerationOptions — ปรับแต่งพฤติกรรมโมเดลได้ตามใจ
บางทีคุณอาจอยากได้ผลลัพธ์ที่คงที่ (deterministic) หรืออยากจำกัดความยาวของคำตอบ ซึ่งทำได้ผ่าน GenerationOptions:
let options = GenerationOptions(
sampling: .greedy, // ผลลัพธ์แน่นอน ไม่สุ่ม
temperature: 0.3, // ความสร้างสรรค์ต่ำ = ผลลัพธ์คงที่กว่า
maximumResponseTokens: 200 // จำกัดความยาวคำตอบ
)
let response = try await session.respond(
to: "อธิบาย Dependency Injection ใน iOS",
options: options
)
พารามิเตอร์ที่ควรรู้:
sampling: .greedy— เลือก token ที่น่าจะเป็นสูงสุดเสมอ เหมาะกับงานที่ต้องการผลลัพธ์แน่นอนคงที่ทุกครั้งtemperature— ค่ายิ่งสูงผลลัพธ์ยิ่งหลากหลาย ค่ายิ่งต่ำผลลัพธ์ยิ่งนิ่งmaximumResponseTokens— จำกัดความยาวคำตอบ ป้องกันโมเดลตอบยาวเกินไป
ตรวจสอบความพร้อมและจัดการ Error ให้ครบ
เนื่องจากไม่ใช่ทุกอุปกรณ์ที่จะรองรับ Foundation Models ดังนั้นการตรวจสอบความพร้อมเป็นสิ่งที่ขาดไม่ได้เลย ถ้าไม่เช็คแล้วแอป crash ตอน production ก็ไม่สนุกแน่นอน
import FoundationModels
func checkModelAvailability() -> Bool {
let availability = SystemLanguageModel.default.availability
switch availability {
case .available:
return true
case .unavailable(.deviceNotSupported):
print("อุปกรณ์ไม่รองรับ")
return false
case .unavailable(.appleIntelligenceNotEnabled):
print("ยังไม่ได้เปิด Apple Intelligence")
return false
case .unavailable(.modelNotReady):
print("โมเดลยังไม่พร้อมใช้งาน")
return false
default:
print("ไม่สามารถใช้งานได้")
return false
}
}
Error ที่เจอบ่อย
do {
let response = try await session.respond(to: prompt)
print(response.content)
} catch let error as LanguageModelSession.GenerationError {
switch error {
case .exceededContextWindowSize:
// Context window เต็ม (จำกัด 4096 tokens)
// สร้าง session ใหม่
session = LanguageModelSession()
print("Session ถูกรีเซ็ต กรุณาลองใหม่")
default:
print("เกิดข้อผิดพลาด: \(error)")
}
} catch {
print("ข้อผิดพลาดทั่วไป: \(error)")
}
Context window ของโมเดล on-device จำกัดอยู่ที่ 4,096 tokens (รวม input + output) ถ้าส่ง prompt ยาวเกินหรือคุยกันหลายรอบจนเกิน session จะ throw error exceededContextWindowSize วิธีแก้ก็คือสร้าง session ใหม่แล้วเริ่มบทสนทนาใหม่
ตัวอย่างแอปสมบูรณ์: AI Recipe Generator ด้วย SwiftUI
เอาล่ะ มาดูตัวอย่างแอปที่รวมทุกอย่างเข้าด้วยกัน — streaming, @Generable และ SwiftUI ในแอปเดียว:
import SwiftUI
import FoundationModels
@Generable
struct ThaiRecipe {
@Guide(description: "ชื่อเมนูอาหารไทย")
let name: String
@Guide(description: "คำอธิบายสั้น ๆ เกี่ยวกับเมนูนี้")
let description: String
@Guide(description: "รายการวัตถุดิบ")
let ingredients: [String]
@Guide(description: "ขั้นตอนการทำอาหาร")
let steps: [String]
@Guide(description: "เวลาในการปรุงเป็นนาที")
let cookingTime: Int
}
struct RecipeGeneratorView: View {
@State private var session = LanguageModelSession(
instructions: "คุณเป็นเชฟอาหารไทยผู้เชี่ยวชาญ แนะนำสูตรอาหารไทยแท้ ๆ"
)
@State private var recipeName: String?
@State private var recipeDescription: String?
@State private var ingredients: [String]?
@State private var steps: [String]?
@State private var isGenerating = false
var body: some View {
NavigationStack {
ScrollView {
VStack(alignment: .leading, spacing: 16) {
if let name = recipeName {
Text(name)
.font(.title2.bold())
}
if let desc = recipeDescription {
Text(desc)
.foregroundStyle(.secondary)
}
if let items = ingredients, !items.isEmpty {
Text("วัตถุดิบ")
.font(.headline)
ForEach(items, id: \.self) { item in
Label(item, systemImage: "circle.fill")
.font(.caption)
}
}
if let steps = steps, !steps.isEmpty {
Text("วิธีทำ")
.font(.headline)
ForEach(Array(steps.enumerated()), id: \.offset) { index, step in
HStack(alignment: .top) {
Text("\(index + 1).")
.fontWeight(.bold)
Text(step)
}
}
}
}
.padding()
}
.navigationTitle("สูตรอาหาร AI")
.toolbar {
Button("สุ่มเมนู") {
Task { await generateRecipe() }
}
.disabled(isGenerating)
}
}
}
func generateRecipe() async {
isGenerating = true
recipeName = nil
recipeDescription = nil
ingredients = nil
steps = nil
do {
let stream = session.streamResponse(
to: "แนะนำสูตรอาหารไทยจานเดียวแบบสุ่ม",
generating: ThaiRecipe.self
)
for try await partial in stream {
recipeName = partial.name
recipeDescription = partial.description
ingredients = partial.ingredients
steps = partial.steps
}
} catch {
recipeName = "เกิดข้อผิดพลาด"
recipeDescription = error.localizedDescription
}
isGenerating = false
}
}
แอปนี้รวมทุก concept ที่เราพูดถึงมาตลอดบทความ ผู้ใช้กดปุ่ม "สุ่มเมนู" แล้วข้อมูลจะค่อย ๆ ปรากฏขึ้นทีละส่วน — ชื่อเมนูขึ้นก่อน ตามด้วยคำอธิบาย วัตถุดิบ และขั้นตอนการทำ ให้ประสบการณ์ที่ลื่นไหลมาก
ข้อจำกัดที่ต้องรู้ก่อนเอาไปใช้จริง
พูดตรง ๆ ว่า Foundation Models framework ดีมาก แต่มันไม่ใช่คำตอบสำหรับทุกอย่าง มีข้อจำกัดที่ควรรู้ไว้:
- ขนาดโมเดลเล็กกว่า Cloud LLM มาก — โมเดล ~3B เทียบกับ GPT-4 หรือ Claude ที่มีหลายร้อยพันล้านพารามิเตอร์ไม่ได้ คาดหวังความรู้ทั่วไปน้อยกว่า และอาจเจอ hallucination บ้าง
- Context Window จำกัดแค่ 4,096 tokens — รวม input + output ไม่เหมาะกับบทสนทนาที่ยาว ๆ แน่นอน
- ไม่ได้เก่งทุกงาน — Apple เองก็บอกว่าไม่ควรใช้กับการเขียนโค้ด คำนวณคณิตศาสตร์ หรือตอบคำถามเชิงข้อเท็จจริง
- เข้าถึงอินเทอร์เน็ตเองไม่ได้ — ต้องใช้ Tool Calling ถ้าต้องการข้อมูลจากภายนอก
- รองรับอุปกรณ์จำกัด — ต้องเป็น Apple Silicon รุ่นใหม่ ๆ เท่านั้น
- ภาษาที่รองรับยังน้อย — ปัจจุบันรองรับ 9 ภาษา และยังไม่รองรับภาษาไทยโดยตรง
สรุปง่าย ๆ คือ Foundation Models เหมาะกับงานเฉพาะทาง (task-specific) มากกว่าการเป็น chatbot ทั่วไป เช่น สรุปข้อความ สร้าง suggestion แบ่งหมวดหมู่เนื้อหา หรือสร้าง structured data ภายในแอป ถ้าต้องการ chatbot เต็มรูปแบบ ควรใช้ cloud-based LLM ร่วมด้วย
Best Practices ที่ผมแนะนำ
- ตรวจสอบ availability ทุกครั้ง — เตรียม fallback สำหรับอุปกรณ์ที่ไม่รองรับ อย่าปล่อยให้แอป crash
- ใช้ @Generable แทน plain text เมื่อทำได้ — ได้ type-safety และผลลัพธ์ที่คาดเดาได้ ชีวิตง่ายขึ้นเยอะ
- ออกแบบ @Generable struct ให้กระชับ — ใส่เฉพาะ property ที่จะใช้จริง เพราะโมเดลต้องสร้างทุก property
- ใส่ใจลำดับ property — ตัวที่ถูกอ้างอิงต้องมาก่อนเสมอ
- ใช้ streaming สำหรับ UX ที่ดี — ลด perceived latency ให้ผู้ใช้รู้สึกว่าแอปตอบสนองเร็ว
- เรียก prewarm() ล่วงหน้า — เมื่อคาดว่าผู้ใช้จะใช้ AI ในไม่กี่วินาที
- จัดการ context window — สร้าง session ใหม่เมื่อบทสนทนายาวเกินไป อย่าปล่อยให้ throw error
- ใช้ Tool Calling สำหรับข้อมูลภายนอก — อย่าหวังให้โมเดลรู้ข้อมูล real-time ด้วยตัวเอง
คำถามที่พบบ่อย (FAQ)
Foundation Models framework ใช้ได้กับ iPhone รุ่นไหนบ้าง?
ต้องเป็น iPhone 15 Pro ขึ้นไป (ชิป A17 Pro) พร้อม iOS 26 และเปิด Apple Intelligence ไว้ iPhone 15 รุ่นปกติหรือรุ่นเก่ากว่าใช้ไม่ได้ แม้จะอัปเดต iOS 26 แล้วก็ตาม
Foundation Models ใช้งานออฟไลน์ได้ไหม?
ได้เลย เพราะโมเดลรันบนอุปกรณ์ทั้งหมด ไม่ต้องต่อเน็ต แต่ถ้าคุณใช้ Tool Calling เพื่อดึงข้อมูลจากภายนอก (เช่น เรียก API สภาพอากาศ) ส่วนนั้นอาจต้องการอินเทอร์เน็ตนะ
@Generable กับ Codable ต่างกันยังไง?
Codable ใช้สำหรับ encode/decode ข้อมูลที่มีอยู่แล้ว (เช่น JSON จาก API) ส่วน @Generable ใช้ให้ AI สร้าง ข้อมูลใหม่ตาม schema ที่กำหนด โดยบังคับที่ระดับ token generation ไม่ใช่แค่ parse ข้อความธรรมดา
Context Window 4,096 tokens หมายความว่าอะไร?
หมายถึงจำนวน token สูงสุดที่โมเดลรับได้ (รวม prompt + response) ถ้าเกินจะ throw error ประมาณคร่าว ๆ 1 token เท่ากับประมาณ 0.75 คำในภาษาอังกฤษ ดังนั้นการสนทนายาว ๆ หรือ prompt ที่ซับซ้อนอาจถึงขีดจำกัดได้เร็วกว่าที่คิด
ใช้ Foundation Models สร้าง chatbot ทั่วไปได้ไหม?
ไม่แนะนำครับ โมเดล ~3B parameter ไม่ได้ออกแบบมาเป็น chatbot ทั่วไป แต่เหมาะกับงานเฉพาะทางมากกว่า เช่น สรุปข้อความ สร้าง suggestion จำแนกหมวดหมู่ หรือสร้าง structured data ในแอป ถ้าต้องการ chatbot เต็มรูปแบบ ควรใช้ cloud-based LLM อย่าง ChatGPT API หรือ Claude API ร่วมด้วย