Foundation Models는 Swift 환경에서 프롬프트(prompt) 기반의 언어 모델을 쉽고 안전하게 사용할 수 있게 해주는 공식 Apple 프레임워크입니다. 핵심 특징은 다음과 같습니다:
실전 시나리오 예시: 챗봇, 키워드 추천, 일정 생성, 감정 분석, 자동 태깅 등
아주 기본적인 LLM 활용 흐름은 LanguageModelSession을 만들고, 프롬프트와 함께 respond(to:)를 호출하는 것부터 시작합니다.
let session = LanguageModelSession()
let response = try await session.respond(to: "What's a good name for a trip to Japan? Respond only with a title")
print(response.content)
// 예시: "Sakura Expedition"와 같이 이름만 출력
실제 프로젝트에서는 배열 등 여러 건에 대해 반복 호출할 수 있습니다.
for landmark in ModelData.shared.landmarks {
let response = try await session.respond(to: "What's a good name for a trip to \(landmark.name)? Respond only with a title")
print(response.content)
}
@Generable은 Swift의 구조체(struct)가 언어 모델의 프롬프트 결과로 자동 생성될 수 있음을 선언하는 속성입니다. 쉽게 말해,
@Generable
struct SearchSuggestions {
@Guide(description: "A list of suggested search terms", .count(4))
var searchTerms: [String]
}
let prompt = """
Generate a list of suggested search terms for an app about visiting famous landmarks.
"""
let response = try await session.respond(to: prompt, generating: SearchSuggestions.self)
print(response.content) // ["Landmark explorer", "Historic journeys", ...]와 같이 리스트 출력
@Generable
struct Person {
var name: String
var phone: String
}
@Generable
struct Itinerary {
var destination: String
var days: Int
var budget: Float
var rating: Double
var requiresVisa: Bool
var activities: [String]
var emergencyContact: Person
var relatedItineraries: [Itinerary]
}
이 구조체는 내부에 다시 구조체, 배열, Bool 등 실전 데이터 모델을 다양하게 받을 수 있습니다.
프롬프트 결과가 크거나 스트리밍할 때는 부분 생성 타입(PartiallyGenerated)으로 중간중간 결과를 받을 수 있습니다.
@Generable
struct Itinerary {
var name: String
var days: [Day]
}
let stream = session.streamResponse(to: "Craft a 3-day itinerary to Mt. Fuji.", generating: Itinerary.self)
for try await partial in stream {
print(partial)
}
struct ItineraryView: View {
let session: LanguageModelSession
let dayCount: Int
let landmarkName: String
@State private var itinerary: Itinerary.PartiallyGenerated?
var body: some View {
Button("Start") {
Task {
let prompt = """
Generate a \(dayCount) itinerary to \(landmarkName).
"""
let stream = session.streamResponse(to: prompt, generating: Itinerary.self)
for try await partial in stream {
itinerary = partial
}
}
}
}
}
외부 날씨 API 등과 연동하는 예시도 내장 지원됩니다.
import WeatherKit
import CoreLocation
import FoundationModels
struct GetWeatherTool: Tool {
let name = "getWeather"
let description = "Retrieve the latest weather information for a city"
@Generable
struct Arguments {
@Guide(description: "The city to fetch the weather for")
var city: String
}
func call(arguments: Arguments) async throws -> ToolOutput {
let places = try await CLGeocoder().geocodeAddressString(arguments.city)
let weather = try await WeatherService.shared.weather(for: places.first!.location!)
let temperature = weather.currentWeather.temperature.value
let content = GeneratedContent(properties: ["temperature": temperature])
return ToolOutput(content)
}
}
let session = LanguageModelSession(tools: [GetWeatherTool()], instructions: "Help the user with weather forecasts.")
let response = try await session.respond(to: "What is the temperature in Cupertino?")
print(response.content) // 예시: "Cupertino의 현재 온도는 71˚F입니다."
let session = LanguageModelSession(
instructions: "You are a helpful assistant who always responds in rhyme."
)
let response = try await session.respond(to: "Write a haiku about fishing")
print(response.content)
@Guide(description: "A list of suggested search terms", .count(4))
var searchTerms: [String]Foundation Models 프레임워크와 @Generable은 Swift 기반 AI 서비스 개발에서 타입 안정성과 예측력을 동시에 확보할 수 있는 강력한 도구입니다. 프롬프트와 구조체 조합, 스트리밍, 툴 API 연동까지 모두 지원해서, SwiftUI 앱을 만들 때 직접 써보면 빠르게 진가를 체감할 수 있습니다.
어떤 시나리오가 궁금한지, 혹은 세부 기능별로 추가 해설이 필요하다면 댓글이나 추가 질문 남겨주세요!