Section 14/151 menit

14. Real Use Cases

14. Real Use Cases

Use Case 1: Smart Journal — Analisis Sentimen dan Insight Pribadi

Aplikasi jurnal yang menganalisis entri pengguna secara privat, memberikan insight tanpa data keluar dari perangkat.

swift
import FoundationModels
import SwiftData

@Generable
enum MoodLabel: String {
    case joyful, content, neutral, anxious, sad, angry
}

@Generable
struct JournalInsight {
    @Guide(description: "Label mood dominan dari entri jurnal")
    var mood: MoodLabel

    @Guide(description: "Tema atau topik utama yang dibahas dalam entri")
    var mainThemes: [String]

    @Guide(description: "Satu kalimat refleksi positif untuk pengguna")
    var positiveAffirmation: String

    @Guide(description: "Satu pertanyaan reflektif untuk mendorong introspeksi lebih dalam")
    var reflectionPrompt: String
}

@Observable
class JournalAnalyzer {
    private var session: LanguageModelSession?

    init() {
        guard case .available = SystemLanguageModel.default.availability else { return }
        session = LanguageModelSession(
            instructions: Instructions("""
            Kamu adalah companion jurnal yang empatik dan suportif. \
            Analisis entri jurnal dengan penuh pengertian. \
            Jangan bersifat judgmental. \
            Fokus pada pertumbuhan dan pemahaman diri.
            """)
        )
    }

    func analyze(journalEntry: String) async throws -> JournalInsight? {
        guard let session else { return nil }

        let response = try await session.respond(
            to: "Analisis entri jurnal berikut:\n\n\(journalEntry)",
            generating: JournalInsight.self
        )
        return response.content
    }
}

// Contoh penggunaan di SwiftUI view
struct JournalEntryView: View {
    let entry: JournalEntry
    @State private var insight: JournalInsight?
    @State private var analyzer = JournalAnalyzer()
    @State private var isAnalyzing = false

    var body: some View {
        ScrollView {
            VStack(alignment: .leading, spacing: 16) {
                Text(entry.text)
                    .font(.body)

                if let insight {
                    InsightCard(insight: insight)
                }

                Button("Analisis Entri Ini") {
                    Task {
                        isAnalyzing = true
                        insight = try? await analyzer.analyze(journalEntry: entry.text)
                        isAnalyzing = false
                    }
                }
                .disabled(isAnalyzing)
                .overlay {
                    if isAnalyzing { ProgressView() }
                }
            }
            .padding()
        }
        .navigationTitle(entry.date.formatted(date: .abbreviated, time: .omitted))
    }
}

struct InsightCard: View {
    let insight: JournalInsight

    var body: some View {
        VStack(alignment: .leading, spacing: 8) {
            Label("Mood: \(insight.mood.rawValue.capitalized)", systemImage: "heart.fill")
                .font(.headline)

            Text(insight.positiveAffirmation)
                .italic()
                .foregroundStyle(.secondary)

            Text("Refleksi: \(insight.reflectionPrompt)")
                .font(.callout)
        }
        .padding()
        .background(.quaternary, in: RoundedRectangle(cornerRadius: 12))
    }
}

Use Case 2: Smart Receipt Parser — Ekstraksi Data Terstruktur

Aplikasi keuangan yang mengekstrak data dari foto atau teks receipt secara privat, tanpa mengirim informasi finansial ke server.

swift
import FoundationModels

@Generable
struct ReceiptItem {
    @Guide(description: "Nama item atau produk")
    var name: String

    @Guide(description: "Jumlah/kuantitas item")
    var quantity: Int

    @Guide(description: "Harga per unit dalam rupiah")
    var unitPriceIDR: Int

    @Guide(description: "Total harga item (quantity × unit price)")
    var totalPriceIDR: Int
}

@Generable
struct ParsedReceipt {
    @Guide(description: "Nama toko atau merchant")
    var merchantName: String

    @Guide(description: "Tanggal transaksi dalam format YYYY-MM-DD, nil jika tidak ditemukan")
    var transactionDate: String?

    @Guide(description: "Daftar item yang dibeli")
    var items: [ReceiptItem]

    @Guide(description: "Total belanja sebelum pajak")
    var subtotalIDR: Int

    @Guide(description: "Jumlah pajak, 0 jika tidak ada")
    var taxIDR: Int

    @Guide(description: "Total keseluruhan termasuk pajak")
    var grandTotalIDR: Int

    @Guide(description: "Kategori pengeluaran: makanan, transportasi, belanja, hiburan, kesehatan, lainnya")
    var category: String
}

class ReceiptParser {
    private let session: LanguageModelSession

    init() {
        session = LanguageModelSession(
            instructions: Instructions("""
            Kamu adalah parser receipt yang akurat. \
            Ekstrak semua informasi dari teks receipt dengan teliti. \
            Jika nilai tidak ditemukan, gunakan 0 untuk angka dan nil untuk string opsional. \
            Semua harga dalam satuan rupiah bulat (integer).
            """)
        )
    }

    func parse(receiptText: String) async throws -> ParsedReceipt {
        let response = try await session.respond(
            to: "Parse receipt berikut:\n\n\(receiptText)",
            generating: ParsedReceipt.self
        )
        return response.content
    }
}

// Contoh penggunaan
func demonstrateReceiptParsing() async throws {
    let parser = ReceiptParser()

    let sampleReceipt = """
    SUPERMARKET MAJU JAYA
    Jl. Sudirman No. 45, Jakarta
    Tanggal: 22/05/2026  14:30

    Beras Premium 5kg    x2    @45.000    90.000
    Minyak Goreng 2L     x1    @32.000    32.000
    Susu UHT 1L          x3    @18.500    55.500
    Telur Kampung 1kg    x2    @28.000    56.000

    Subtotal:           233.500
    PPN 11%:             25.685
    TOTAL:              259.185
    """

    let receipt = try await parser.parse(receiptText: sampleReceipt)
    print("Merchant:", receipt.merchantName)
    print("Total:", receipt.grandTotalIDR)
    print("Kategori:", receipt.category)
    print("Item count:", receipt.items.count)
    for item in receipt.items {
        print("  -", item.name, "x\(item.quantity) =", item.totalPriceIDR)
    }
}

Use Case 3: Code Review Assistant — Tool Calling untuk Konteks Kode

IDE companion yang menganalisis kode Swift dengan akses ke dokumentasi dan linting secara real-time.

swift
import FoundationModels

// Tool untuk mengambil dokumentasi API Swift
struct SwiftDocsTool: Tool {
    let name = "lookup_swift_docs"
    let description = "Mencari dokumentasi resmi Swift untuk type, method, atau protocol tertentu"

    @Generable
    struct Arguments {
        @Guide(description: "Nama type, method, atau protocol Swift yang ingin dicari dokumentasinya")
        var symbolName: String
    }

    func call(arguments: Arguments) async throws -> ToolOutput {
        // Dalam implementasi nyata: query ke DocC atau Apple Developer docs
        return ToolOutput("Dokumentasi untuk \(arguments.symbolName): [mock documentation content]")
    }
}

// Tool untuk menjalankan SwiftLint
struct SwiftLintTool: Tool {
    let name = "run_swiftlint"
    let description = "Menjalankan SwiftLint pada kode dan mengembalikan warning/error"

    @Generable
    struct Arguments {
        @Guide(description: "Kode Swift yang akan di-lint")
        var code: String
    }

    func call(arguments: Arguments) async throws -> ToolOutput {
        // Dalam implementasi nyata: jalankan SwiftLint via Process
        let mockWarnings = arguments.code.contains("force_try") ?
            "Warning: force_try di baris 5 — gunakan try? atau do-catch" : "Tidak ada issue ditemukan"
        return ToolOutput(mockWarnings)
    }
}

@Generable
struct CodeReviewResult {
    @Guide(description: "Daftar masalah potensial dalam kode (kosong jika tidak ada)")
    var issues: [String]

    @Guide(description: "Saran perbaikan yang konkret")
    var suggestions: [String]

    @Guide(description: "Skor kualitas kode dari 1-10")
    var qualityScore: Int

    @Guide(description: "Apakah kode aman untuk di-merge ke production")
    var isProductionReady: Bool
}

class CodeReviewAssistant {
    private let session: LanguageModelSession

    init() {
        session = LanguageModelSession(
            instructions: Instructions("""
            Kamu adalah senior Swift engineer yang melakukan code review. \
            Fokus pada: correctness, performance, Swift best practices, dan thread safety. \
            Gunakan tools yang tersedia untuk mendapatkan konteks tambahan. \
            Berikan review yang konstruktif dan actionable.
            """),
            tools: [SwiftDocsTool(), SwiftLintTool()]
        )
    }

    func review(code: String, context: String = "") async throws -> CodeReviewResult {
        let prompt = context.isEmpty ?
            "Review kode Swift berikut:\n\n```swift\n\(code)\n```" :
            "Review kode Swift berikut (konteks: \(context)):\n\n```swift\n\(code)\n```"

        let response = try await session.respond(
            to: prompt,
            generating: CodeReviewResult.self
        )
        return response.content
    }
}

Use Case 4: Writing Assistant dengan Streaming Real-Time

Feature writing assistant yang terintegrasi dalam text editor in-app, dengan feedback langsung saat pengguna mengetik.

swift
import FoundationModels
import SwiftUI

@Generable
enum ImprovementType: String {
    case grammar
    case clarity
    case tone
    case structure
    case conciseness
}

@Generable
struct WritingSuggestion {
    @Guide(description: "Jenis perbaikan yang disarankan")
    var type: ImprovementType

    @Guide(description: "Teks asli yang perlu diperbaiki")
    var originalText: String

    @Guide(description: "Versi teks yang sudah diperbaiki")
    var improvedText: String

    @Guide(description: "Penjelasan singkat mengapa perubahan ini disarankan")
    var explanation: String
}

@Observable
class WritingAssistantViewModel {
    var suggestions: [WritingSuggestion] = []
    var isAnalyzing = false
    var improvedDraft = ""

    private var session: LanguageModelSession?
    private var analysisTask: Task<Void, Never>?

    init() {
        guard case .available = SystemLanguageModel.default.availability else { return }
        session = LanguageModelSession(
            instructions: Instructions("""
            Kamu adalah editor tulisan profesional yang membantu meningkatkan kualitas teks. \
            Fokus pada kejelasan, konsistensi, dan dampak komunikasi. \
            Pertahankan suara dan gaya penulis asli.
            """)
        )
    }

    func analyzeDraft(_ text: String) {
        analysisTask?.cancel()
        analysisTask = Task {
            guard let session, !text.trimmingCharacters(in: .whitespaces).isEmpty else { return }
            isAnalyzing = true
            defer { isAnalyzing = false }
            improvedDraft = ""

            do {
                let stream = session.streamResponse(
                    to: "Perbaiki draft tulisan berikut dan tampilkan versi yang sudah disempurnakan:\n\n\(text)"
                )
                for try await partial in stream {
                    guard !Task.isCancelled else { break }
                    improvedDraft = partial.content
                }
            } catch {
                if !(error is CancellationError) {
                    improvedDraft = "Error: \(error.localizedDescription)"
                }
            }
        }
    }
}