MoodDetectionService,主要根據使用者輸入的文字,自動偵測並判斷心情。用於聊天室,讓系統能根據使用者的心情給予更貼近需求的回應或建議。
核心功能說明:
關鍵字比對
服務初始化時,依照已定義的心情相關的關鍵字,例如「開心」、「放鬆」、「疲憊」、「專注」等,以及英文對應詞(如 happy, relaxed, tired),將使用者的輸入分割成詞語,然後逐一比對每個 mood 的關鍵字,並根據關鍵字長度加分。系統會先將內容轉為小寫,並根據偵測到的關鍵字,判定對應的心情。若有多個心情被偵測,取分數最高者,並依分數計算信心度。
private final Map<String, Set<String>> moodKeywords = initializeMoodKeywords();
private String getMoodDescription(String mood) {
    switch (mood) {
        case "happy": return "開心愉快";
        case "relaxed": return "放鬆平靜";
        case "tired": return "疲憊想休息";
        case "energetic": return "充滿活力";
        case "stressed": return "有壓力焦慮";
        case "sad": return "傷心沮喪";
        case "romantic": return "浪漫溫馨";
        case "focused": return "專注工作";
        case "refreshed": return "需要清爽";
        case "cozy": return "溫暖舒適";
        default: return "中性心情";
    }
}
private Map<String, Set<String>> initializeMoodKeywords() {
    Map<String, Set<String>> keywords = new HashMap<>();
    // 開心/興奮
    keywords.put("happy", new HashSet<>(Arrays.asList(
        "開心", "高興", "快樂", "興奮", "激動", "愉快", "喜悅", "歡樂",
        "happy", "excited", "joyful", "cheerful", "delighted", "elated"
    )));
    // 放鬆/平靜
    keywords.put("relaxed", new HashSet<>(Arrays.asList(
        "放鬆", "平靜", "安靜", "冷靜", "舒服", "悠閒", "輕鬆", "寧靜",
        "relaxed", "calm", "peaceful", "tranquil", "serene", "zen"
    )));
    // 疲憊/累
    keywords.put("tired", new HashSet<>(Arrays.asList(
        "累", "疲憊", "疲勞", "困", "想睡", "無力", "倦", "乏",
        "tired", "exhausted", "weary", "sleepy", "drained", "fatigue"
    )));
    // 有活力/精神
    keywords.put("energetic", new HashSet<>(Arrays.asList(
        "有活力", "精神", "充滿活力", "有精神", "清醒", "振奮", "活躍",
        "energetic", "vigorous", "lively", "active", "alert", "refreshed"
    )));
    // 壓力/焦慮
    keywords.put("stressed", new HashSet<>(Arrays.asList(
        "壓力", "焦慮", "緊張", "煩躁", "不安", "憂心", "緊迫", "煩惱",
        "stressed", "anxious", "worried", "nervous", "tense", "overwhelmed"
    )));
    // 悲傷/沮喪
    keywords.put("sad", new HashSet<>(Arrays.asList(
        "傷心", "難過", "沮喪", "憂鬱", "低落", "失望", "鬱悶", "悲傷",
        "sad", "depressed", "down", "disappointed", "melancholy", "blue"
    )));
    // 浪漫/溫馨
    keywords.put("romantic", new HashSet<>(Arrays.asList(
        "浪漫", "甜蜜", "溫馨", "約會", "情人", "戀愛", "愛情",
        "romantic", "warm", "sweet", "intimate", "loving"
        // "cozy" 已移除,避免與 cozy mood 混淆
    )));
    // 專注/工作
    keywords.put("focused", new HashSet<>(Arrays.asList(
        "專注", "工作", "學習", "讀書", "思考", "集中", "努力", "認真",
        "focused", "concentrated", "studying", "working", "productive"
    )));
    // 清爽/提神
    keywords.put("refreshed", new HashSet<>(Arrays.asList(
        "清爽", "提神", "refresh", "refreshed", "醒腦", "涼快", "cool", "fresh"
    )));
    // 溫暖/舒適
    keywords.put("cozy", new HashSet<>(Arrays.asList(
        "溫暖", "舒適", "cozy", "暖和", "暖", "comfortable", "snug"
    )));
    return keywords;
}
public MoodDetectionResult detectMood(String input) {
    if (input == null || input.trim().isEmpty()) {
        return new MoodDetectionResult("neutral", "無特定心情", 0.0);
    }
    String lowerInput = input.toLowerCase();
    Map<String, Integer> moodScores = new HashMap<>();
    // 以空白、標點分割詞語
    String[] words = lowerInput.split("[\\s\\p{Punct}]+");
    Set<String> wordSet = new HashSet<>(Arrays.asList(words));
    // 計算每種心情的匹配分數(完整詞語比對)
    for (Map.Entry<String, Set<String>> entry : moodKeywords.entrySet()) {
        String mood = entry.getKey();
        Set<String> keywords = entry.getValue();
        int score = 0;
        for (String keyword : keywords) {
            String lowerKeyword = keyword.toLowerCase();
            // 完整詞語比對
            if (wordSet.contains(lowerKeyword)) {
                score += lowerKeyword.length(); // 較長的關鍵字有更高的權重
            }
        }
        if (score > 0) {
            moodScores.put(mood, score);
        }
    }
    // 找出最高分的心情
    if (moodScores.isEmpty()) {
        return detectMoodFromContext(input);
    }
    String detectedMood = Collections.max(moodScores.entrySet(), 
                                        Map.Entry.comparingByValue()).getKey();
    int maxScore = moodScores.get(detectedMood);
    double confidence = Math.min(maxScore / 10.0, 1.0); // 信心度標準化為 0-1
  return new MoodDetectionResult(detectedMood, getMoodDescription(detectedMood), confidence);
}
情境推測
除了直接比對的心情關鍵字,MoodDetectionService 也能透過分析輸入中的時間(早上、晚上)、天氣(炎熱、寒冷)等。這些情境詞彙有助於推測使用者可能的心情,例如「寒冷的天氣很適合喝熱茶放鬆」,系統可判斷「放鬆」為主要心情。讓系統在沒有明確心情關鍵字時,依據情境詞彙判斷最可能的心情。
private MoodDetectionResult detectMoodFromContext(String input) {
    String lowerInput = input.toLowerCase();
    // 時間相關的心情推測
    if (lowerInput.contains("早上") || lowerInput.contains("morning")) {
        return new MoodDetectionResult("energetic", "早晨需要活力", 0.6);
    }
    if (lowerInput.contains("下午") || lowerInput.contains("afternoon")) {
        return new MoodDetectionResult("focused", "下午工作時光", 0.5);
    }
    if (lowerInput.contains("晚上") || lowerInput.contains("evening") || 
        lowerInput.contains("夜晚") || lowerInput.contains("night")) {
        return new MoodDetectionResult("relaxed", "夜晚放鬆時刻", 0.6);
    }
    // 天氣相關的心情推測
    if (lowerInput.contains("熱") || lowerInput.contains("夏天") || lowerInput.contains("hot")) {
        return new MoodDetectionResult("refreshed", "炎熱天氣", 0.5);
    }
    if (lowerInput.contains("冷") || lowerInput.contains("冬天") || lowerInput.contains("cold")) {
        return new MoodDetectionResult("cozy", "寒冷天氣", 0.5);
    }
    // 默認中性心情
    return new MoodDetectionResult("neutral", "中性心情", 0.3);
}
回傳心情類型、描述與信心度
最終,當偵測到心情後,MoodDetectionService 會回傳一個結果物件,內容包含:
心情類型 mood(如「relaxed」、「tired」)
public static class MoodDetectionResult {
    private final String mood;
    private final String description;
    private final double confidence;
    public MoodDetectionResult(String mood, String description, double confidence) {
        this.mood = mood;
        this.description = description;
        this.confidence = confidence;
    }
    public String getMood() { return mood; }
    public String getDescription() { return description; }
    public double getConfidence() { return confidence; }
}
運作流程:
總結來說,MoodDetectionService 讓系統能根據使用者輸入內容,回傳心情類型(mood)、心情描述(description)以及信心度(confidence),使推薦更符合使用者當下情緒,進一步提升互動體驗與推薦的準確度。
參考資料: