Section 6/151 menit

6. Structured Output dengan @Generable

6. Structured Output dengan @Generable

@Generable adalah cara paling andal untuk mendapatkan output terstruktur dari model. Macro ini menghasilkan conformance ke protokol Generable yang memberikan schema ke model.

@Generable Dasar

swift
import FoundationModels

@Generable
struct TravelPlan {
    @Guide(description: "Nama destinasi wisata")
    var destination: String

    @Guide(description: "Estimasi biaya dalam rupiah")
    var estimatedCostIDR: Int

    @Guide(description: "Durasi perjalanan yang disarankan dalam hari")
    var recommendedDays: Int

    @Guide(description: "Tiga aktivitas utama yang wajib dilakukan")
    var mustDoActivities: [String]
}

func generateTravelPlan(for city: String) async throws -> TravelPlan {
    let session = LanguageModelSession()
    let response = try await session.respond(
        to: "Buat rencana perjalanan singkat untuk \(city)",
        generating: TravelPlan.self
    )
    return response.content
}

// Penggunaan
let plan = try await generateTravelPlan(for: "Yogyakarta")
print("Destinasi:", plan.destination)
print("Biaya estimasi:", plan.estimatedCostIDR)
print("Aktivitas:", plan.mustDoActivities.joined(separator: ", "))

@Generable dengan Enum

Model dapat menghasilkan nilai dari set pilihan yang terbatas menggunakan enum:

swift
@Generable
enum SentimentLabel: String {
    case positive
    case negative
    case neutral
}

@Generable
struct SentimentAnalysis {
    @Guide(description: "Label sentimen keseluruhan teks")
    var sentiment: SentimentLabel

    @Guide(description: "Skor kepercayaan dari 0.0 hingga 1.0")
    var confidence: Double

    @Guide(description: "Kata kunci yang menjadi dasar analisis")
    var keyPhrases: [String]
}

func analyzeSentiment(of text: String) async throws -> SentimentAnalysis {
    let session = LanguageModelSession()
    let response = try await session.respond(
        to: "Analisis sentimen dari teks berikut: \"\(text)\"",
        generating: SentimentAnalysis.self
    )
    return response.content
}

@Generable Bersarang (Nested)

Struct @Generable bisa bersarang untuk output yang lebih kompleks:

swift
@Generable
struct Address {
    @Guide(description: "Nama jalan")
    var street: String

    @Guide(description: "Nama kota")
    var city: String

    @Guide(description: "Kode pos 5 digit")
    var postalCode: String
}

@Generable
struct ContactCard {
    @Guide(description: "Nama lengkap")
    var fullName: String

    @Guide(description: "Alamat email")
    var email: String

    @Guide(description: "Alamat lengkap")
    var address: Address

    @Guide(description: "Nomor telepon dengan format internasional")
    var phoneNumber: String
}

func extractContactInfo(from text: String) async throws -> ContactCard {
    let session = LanguageModelSession()
    let response = try await session.respond(
        to: "Ekstrak informasi kontak dari teks ini: \(text)",
        generating: ContactCard.self
    )
    return response.content
}

Optional Fields dalam @Generable

swift
@Generable
struct BookRecommendation {
    @Guide(description: "Judul buku")
    var title: String

    @Guide(description: "Nama penulis")
    var author: String

    @Guide(description: "Tahun terbit jika diketahui, nil jika tidak")
    var publishYear: Int?

    @Guide(description: "Genre utama buku")
    var genre: String

    @Guide(description: "Alasan singkat mengapa buku ini direkomendasikan")
    var reason: String
}