// // FoundationModelsReflectionService.swift // Reflect // // Generates personalized AI feedback after a user completes a guided reflection. // import Foundation import FoundationModels @available(iOS 26, *) @MainActor class FoundationModelsReflectionService { // MARK: - Initialization init() {} // MARK: - Feedback Generation /// Generate personalized feedback based on a completed guided reflection /// - Parameters: /// - reflection: The completed guided reflection with Q&A responses /// - mood: The mood associated with this entry /// - Returns: AI-generated reflection feedback func generateFeedback( for reflection: GuidedReflection, mood: Mood ) async throws -> AIReflectionFeedback { let session = LanguageModelSession(instructions: systemInstructions) let prompt = buildPrompt(from: reflection, mood: mood) let response = try await session.respond( to: prompt, generating: AIReflectionFeedback.self ) return response.content } // MARK: - System Instructions private var systemInstructions: String { let personalityPack = UserDefaultsStore.personalityPackable() switch personalityPack { case .Default: return defaultInstructions case .MotivationalCoach: return coachInstructions case .ZenMaster: return zenInstructions case .BestFriend: return bestFriendInstructions case .DataAnalyst: return analystInstructions } } private var defaultInstructions: String { """ You are a warm, supportive companion responding to someone who just completed a guided mood reflection. \ Validate their effort, reflect their own words back to them, and offer a gentle takeaway. \ Be specific — reference what they actually wrote. Keep each field to 1 sentence. \ SF Symbols: sparkles, heart.fill, star.fill, sun.max.fill, leaf.fill """ } private var coachInstructions: String { """ You are a HIGH ENERGY motivational coach responding to someone who just completed a guided mood reflection! \ Celebrate their self-awareness, pump them up about the growth they showed, and give them a power move for tomorrow. \ Reference what they actually wrote. Keep each field to 1 sentence. Use exclamations! \ SF Symbols: trophy.fill, flame.fill, bolt.fill, star.fill, figure.run """ } private var zenInstructions: String { """ You are a calm, mindful guide responding to someone who just completed a guided mood reflection. \ Acknowledge their practice of self-awareness with gentle wisdom. Use nature metaphors. \ Reference what they actually wrote. Keep each field to 1 sentence. Speak with serene clarity. \ SF Symbols: leaf.fill, moon.fill, drop.fill, sunrise.fill, wind """ } private var bestFriendInstructions: String { """ You are their supportive best friend responding after they completed a guided mood reflection. \ Be warm, casual, and validating. Use conversational tone. \ Reference what they actually wrote. Keep each field to 1 sentence. \ SF Symbols: heart.fill, hand.thumbsup.fill, sparkles, star.fill, face.smiling.fill """ } private var analystInstructions: String { """ You are a clinical data analyst providing feedback on a completed mood reflection. \ Note the cognitive patterns observed, the technique application quality, and a data-informed recommendation. \ Reference what they actually wrote. Keep each field to 1 sentence. Be objective but encouraging. \ SF Symbols: chart.bar.fill, brain.head.profile, doc.text.magnifyingglass, chart.line.uptrend.xyaxis """ } // MARK: - Prompt Construction private func buildPrompt(from reflection: GuidedReflection, mood: Mood) -> String { let moodName = mood.widgetDisplayName let technique = reflection.moodCategory.techniqueName let qaPairs = reflection.responses .filter { !$0.answer.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty } .map { response in let chips = response.selectedChips.isEmpty ? "" : " [themes: \(response.selectedChips.joined(separator: ", "))]" return "Q: \(response.question)\nA: \(response.answer)\(chips)" } .joined(separator: "\n\n") return """ The user logged their mood as "\(moodName)" and completed a \(technique) reflection: \(qaPairs) Respond with personalized feedback that references their specific answers. """ } }