Pass raw health metrics to AI instead of hardcoded correlations

- Replace HealthService.analyzeCorrelations() with computeHealthAverages()
- Remove hardcoded threshold-based correlation analysis (8k steps, 7hrs sleep, etc.)
- Pass raw averages (steps, exercise, sleep, HRV, HR, mindfulness, calories) to AI
- Let Apple Intelligence find nuanced multi-variable patterns naturally
- Update MoodDataSummarizer to format raw health data for AI prompts
- Simplifies code by ~200 lines while improving insight quality

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Trey t
2025-12-22 09:42:45 -06:00
parent 742b7b00d4
commit 2e9e28d00b
5 changed files with 351 additions and 143 deletions

View File

@@ -47,15 +47,8 @@ struct MoodDataSummary {
let hasAllMoodTypes: Bool
let missingMoodTypes: [String]
// Health correlations (optional)
let healthCorrelations: [HealthCorrelation]
}
/// Health correlation data for AI insights
struct HealthCorrelation {
let metric: String
let insight: String
let correlation: String // "positive", "negative", or "none"
// Health data for AI analysis (optional)
let healthAverages: HealthService.HealthAverages?
}
/// Transforms raw MoodEntryModel data into AI-optimized summaries
@@ -69,7 +62,7 @@ class MoodDataSummarizer {
// MARK: - Main Summarization
func summarize(entries: [MoodEntryModel], periodName: String, healthCorrelations: [HealthCorrelation] = []) -> MoodDataSummary {
func summarize(entries: [MoodEntryModel], periodName: String, healthAverages: HealthService.HealthAverages? = nil) -> MoodDataSummary {
let validEntries = entries.filter { ![.missing, .placeholder].contains($0.mood) }
guard !validEntries.isEmpty else {
@@ -114,7 +107,7 @@ class MoodDataSummarizer {
last7DaysMoods: recentContext.moods,
hasAllMoodTypes: moodTypes.hasAll,
missingMoodTypes: moodTypes.missing,
healthCorrelations: healthCorrelations
healthAverages: healthAverages
)
}
@@ -391,7 +384,7 @@ class MoodDataSummarizer {
last7DaysMoods: [],
hasAllMoodTypes: false,
missingMoodTypes: ["great", "good", "average", "bad", "horrible"],
healthCorrelations: []
healthAverages: nil
)
}
@@ -423,12 +416,57 @@ class MoodDataSummarizer {
// Stability
lines.append("Stability: \(String(format: "%.0f", summary.moodStabilityScore * 100))%, Mood swings: \(summary.moodSwingCount)")
// Health correlations (if available)
if !summary.healthCorrelations.isEmpty {
lines.append("Health correlations:")
for correlation in summary.healthCorrelations {
lines.append("- \(correlation.metric): \(correlation.insight)")
// Health data for AI analysis (if available)
if let health = summary.healthAverages, health.hasData {
lines.append("")
lines.append("Apple Health data (\(health.daysWithHealthData) days with data):")
// Activity metrics
var activityMetrics: [String] = []
if let steps = health.avgSteps {
activityMetrics.append("Steps: \(steps.formatted())/day")
}
if let exercise = health.avgExerciseMinutes {
activityMetrics.append("Exercise: \(exercise) min/day")
}
if let calories = health.avgActiveCalories {
activityMetrics.append("Active cal: \(calories)/day")
}
if let distance = health.avgDistanceKm {
activityMetrics.append("Distance: \(String(format: "%.1f", distance)) km/day")
}
if !activityMetrics.isEmpty {
lines.append("Activity: \(activityMetrics.joined(separator: ", "))")
}
// Heart metrics
var heartMetrics: [String] = []
if let hr = health.avgHeartRate {
heartMetrics.append("Avg HR: \(Int(hr)) bpm")
}
if let restingHR = health.avgRestingHeartRate {
heartMetrics.append("Resting HR: \(Int(restingHR)) bpm")
}
if let hrv = health.avgHRV {
heartMetrics.append("HRV: \(Int(hrv)) ms")
}
if !heartMetrics.isEmpty {
lines.append("Heart: \(heartMetrics.joined(separator: ", "))")
}
// Recovery metrics
var recoveryMetrics: [String] = []
if let sleep = health.avgSleepHours {
recoveryMetrics.append("Sleep: \(String(format: "%.1f", sleep)) hrs/night")
}
if let mindful = health.avgMindfulMinutes {
recoveryMetrics.append("Mindfulness: \(mindful) min/day")
}
if !recoveryMetrics.isEmpty {
lines.append("Recovery: \(recoveryMetrics.joined(separator: ", "))")
}
lines.append("Analyze how these health metrics may correlate with mood patterns.")
}
return lines.joined(separator: "\n")