Section 2/141 menit

2. Session Lifecycle dan Memory Management

2. Session Lifecycle dan Memory Management

Satu Session vs Banyak Session

LanguageModelSession adalah stateful — setiap instance membawa riwayat percakapannya sendiri. Memilih kapan membuat session baru vs mempertahankan session lama adalah keputusan arsitektur penting.

swift
// ❌ TANPA manajemen lifecycle: session baru di tiap request — kehilangan konteks
class SearchViewModel {
    func search(query: String) async throws -> String {
        let session = LanguageModelSession()  // context kosong setiap kali
        // Tidak ada konteks dari query sebelumnya
        return try await session.respond(to: query).content
    }
}
swift
// ✓ DENGAN lifecycle yang tepat: session per conversation thread
class SearchViewModel {
    // Satu session per sesi pencarian user — konteks dipertahankan
    private var activeSession: LanguageModelSession?

    func startNewSearchSession() {
        activeSession = LanguageModelSession(
            instructions: Instructions("Bantu pengguna mencari dan menemukan informasi yang relevan.")
        )
    }

    func search(query: String) async throws -> String {
        guard let session = activeSession else {
            startNewSearchSession()
            return try await search(query: query)
        }
        return try await session.respond(to: query).content
    }

    func endSearchSession() {
        activeSession = nil  // ARC cleanup — context dibuang
    }
}

Pola Scope Session yang Tepat

swift
// Pola 1: Session per layar/fitur (stateful conversation)
@Observable
class ConversationViewModel {
    // Session hidup selama viewModel hidup
    let session = LanguageModelSession()
    var messages: [Message] = []
}

// Pola 2: Session per task (stateless, single-purpose)
struct TextSummarizer {
    func summarize(_ text: String) async throws -> String {
        // Session baru per panggilan — tidak ada konteks yang dipertahankan
        // Tepat untuk task yang benar-benar independen
        let session = LanguageModelSession()
        return try await session.respond(to: "Rangkum: \(text)").content
    }
}

// Pola 3: Session yang dikelola di level app (shared context)
@MainActor
class AppAICoordinator {
    static let shared = AppAICoordinator()

    // Session untuk asisten global yang tahu tentang pengguna
    private(set) lazy var personalAssistantSession: LanguageModelSession = {
        LanguageModelSession(instructions: Instructions(buildPersonalContext()))
    }()

    // Session terpisah untuk fitur analisis dokumen (context berbeda)
    private(set) lazy var documentAnalysisSession: LanguageModelSession = {
        LanguageModelSession(instructions: Instructions("Kamu ahli analisis dokumen legal dan teknis."))
    }()

    private func buildPersonalContext() -> String {
        let username = UserDefaults.standard.string(forKey: "username") ?? "Pengguna"
        return "Kamu adalah asisten pribadi untuk \(username). Jawab secara singkat dan personal."
    }
}

Memory Pressure dan Session Reset

Session menyimpan seluruh riwayat percakapan di memori. Untuk percakapan yang sangat panjang:

swift
@Observable
class LongConversationViewModel {
    private var session: LanguageModelSession
    private var turnCount = 0
    private let maxTurnsBeforeReset = 50

    init() {
        session = LanguageModelSession()
    }

    func sendMessage(_ text: String) async throws -> String {
        turnCount += 1

        // Reset session jika terlalu panjang untuk mencegah context bloat
        // Pertahankan instructions tapi buang riwayat lama
        if turnCount > maxTurnsBeforeReset {
            let summaryPrompt = "Ringkas percakapan kita sejauh ini dalam 3 kalimat."
            let summary = try await session.respond(to: summaryPrompt).content
            
            session = LanguageModelSession(
                instructions: Instructions("Konteks dari percakapan sebelumnya: \(summary)")
            )
            turnCount = 0
        }

        return try await session.respond(to: text).content
    }
}