93 lines
3.5 KiB
Swift
93 lines
3.5 KiB
Swift
import Foundation
|
|
import FoundationModels
|
|
|
|
@Generable
|
|
private struct GeneratedDiaryEntry {
|
|
@Guide(description: "Aktuelle Stimmung", .anyOf(["Sehr gut", "Gut", "Mittel", "Schlecht", "Sehr schlecht"]))
|
|
var mood: String
|
|
|
|
@Guide(description: "Ob die Person gerade Musik oder einen Song im Kopf hat")
|
|
var musicInHead: Bool
|
|
|
|
@Guide(description: "Name des Songs; leer lassen, wenn kein Song genannt wurde")
|
|
var songName: String
|
|
|
|
@Guide(description: "Stärke des Ohrwurms", .anyOf(["Leise", "Mittel", "Laut"]))
|
|
var earwormStrength: String
|
|
|
|
@Guide(description: "Ob heute Sozialkontakt stattgefunden hat")
|
|
var socialContact: Bool
|
|
|
|
@Guide(description: "Leidensdruck durch den Ohrwurm", .anyOf(["Niedrig", "Mittel", "Hoch"]))
|
|
var distress: String
|
|
|
|
@Guide(description: "Ob Gegenmaßnahmen gegen den Ohrwurm versucht wurden")
|
|
var countermeasures: Bool
|
|
|
|
@Guide(description: "Genannte Freizeitaktivität oder Gegenmaßnahme; sonst leer")
|
|
var countermeasureActivity: String
|
|
|
|
@Guide(description: "Ob Stress vorhanden ist")
|
|
var stress: Bool
|
|
}
|
|
|
|
enum MoodAnalysisError: LocalizedError {
|
|
case emptyTranscript
|
|
case modelUnavailable
|
|
|
|
var errorDescription: String? {
|
|
switch self {
|
|
case .emptyTranscript:
|
|
"Es wurde noch kein Text erkannt. Sprich etwas länger oder trage die Angaben manuell ein."
|
|
case .modelUnavailable:
|
|
"Apples lokales KI-Modell ist noch nicht verfügbar. Prüfe, ob Apple Intelligence aktiviert und vollständig geladen ist."
|
|
}
|
|
}
|
|
}
|
|
|
|
struct MoodAnalysisService {
|
|
static func analyze(_ transcript: String) async throws -> DraftMoodEntry {
|
|
let cleanTranscript = transcript.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
guard !cleanTranscript.isEmpty else {
|
|
throw MoodAnalysisError.emptyTranscript
|
|
}
|
|
|
|
let model = SystemLanguageModel.default
|
|
guard model.availability == .available else {
|
|
throw MoodAnalysisError.modelUnavailable
|
|
}
|
|
|
|
let session = LanguageModelSession(
|
|
model: model,
|
|
instructions: """
|
|
Du extrahierst ausschließlich strukturierte Angaben aus einem privaten deutschen Stimmungstagebuch.
|
|
Erfinde keine Songnamen, Aktivitäten oder Erlebnisse.
|
|
Wenn etwas nicht erwähnt wird, verwende für Text ein leeres Feld und für Ja/Nein den Wert false.
|
|
Wenn Musik im Kopf vorhanden ist, ist Stress für diesen Eintrag false.
|
|
Wenn keine Musik im Kopf vorhanden ist, bleiben Songname, Ohrwurmstärke, Leidensdruck und Gegenmaßnahmen auf ihren neutralen Standardwerten.
|
|
Ordne die Stimmung auf der Skala Sehr gut, Gut, Mittel, Schlecht, Sehr schlecht ein.
|
|
Du gibst keine medizinische Einschätzung und keinen Rat.
|
|
"""
|
|
)
|
|
|
|
let response = try await session.respond(
|
|
to: "Analysiere diesen Tagebucheintrag:\n\n\(cleanTranscript)",
|
|
generating: GeneratedDiaryEntry.self
|
|
)
|
|
let value = response.content
|
|
|
|
return DraftMoodEntry(
|
|
mood: .normalized(value.mood),
|
|
musicInHead: value.musicInHead,
|
|
songName: value.songName,
|
|
earwormStrength: .normalized(value.earwormStrength),
|
|
socialContact: value.socialContact,
|
|
distress: .normalized(value.distress),
|
|
countermeasures: value.countermeasures,
|
|
countermeasureActivity: value.countermeasureActivity,
|
|
stress: value.stress,
|
|
transcript: cleanTranscript
|
|
)
|
|
}
|
|
}
|