iT邦幫忙

2025 iThome 鐵人賽

DAY 25
0
自我挑戰組

跟 AI Agent 變成好朋友系列 第 25

【Day25】AI Agent 魔法詠唱 - AIRecommendation Service

  • 分享至 

  • xImage
  •  

AIRecommendationService 是本次系統後端的核心,負責接收使用者輸入與心情,整合多項服務,產生個人化飲品推薦。其主要流程如下:

public RecommendationResponse generateRecommendation(String userInput, String username) {
    try {
        // 1. Guardrails 過濾
        ContentFilterService.ContentFilterResult filterResult =
            contentFilterService.filterContent(userInput);

        if (!filterResult.isValid()) {
            return RecommendationResponse.error(filterResult.getMessage());
        }

        String cleanedInput = filterResult.getCleanedContent();

        // 2. 心情判斷
        MoodDetectionService.MoodDetectionResult moodResult =
            moodDetectionService.detectMood(cleanedInput);

        // 3. 獲取使用者偏好
        User user = null;
        String userPreferences = "";
        List<String> favoriteDrinks = new ArrayList<>();
        System.out.println("Request Username for Preferences: " + username);
        if (username != null && !username.isEmpty()) {
            user = userRepository.findByUsername(username).orElse(null);
            if (user != null) {
                userPreferences = userPreferenceService.buildUserPreferencesString(user);
                favoriteDrinks = favoriteDrinkService.getFavoriteDrinkNamesByUser(user.getUsername());
                System.out.println("User Preferences: " + userPreferences);
                System.out.println("Favorite Drinks: " + favoriteDrinks);
            }
        }

        // 4. 生成推薦 prompt
        String prompt = bedrockAIService.buildRecommendationPrompt(
            cleanedInput, moodResult.getDescription(), userPreferences);
        // 5. Bedrock Nova 推薦清單
        BedrockAIService.RecommendationResult aiResult = bedrockAIService.generateRecommendation(prompt);
        String aiResponse = aiResult.getRecommendation();

        if (aiResponse == null || aiResponse.trim().isEmpty()) {
            aiResponse = "AI 正在學習您的偏好,請稍候...";
            System.out.println("警告:AI 回應為空,使用默認回應");
        }

        String moodDescription = moodResult.getDescription();
        if (moodDescription == null || moodDescription.trim().isEmpty()) {
            moodDescription = "中性心情";
            System.out.println("警告:心情描述為空,使用默認值");
        }

        // 6. MySQL 查菜單細節
        List<RecommendationResponse.DrinkRecommendation> recommendations =
            matchMenuItems(aiResponse, moodResult.getMood());

        if (recommendations == null) {
            recommendations = new ArrayList<>();
            System.out.println("警告:推薦列表為 null,初始化為空列表");
        }

        if (recommendations.isEmpty()) {
            recommendations = generateFallbackRecommendations(moodResult.getMood());
            System.out.println("沒有匹配到推薦,使用備用推薦列表");
        }

        // 7. 保存推薦歷史
        if (user != null) {
            saveRecommendationHistory(user, cleanedInput, moodDescription, prompt, aiResponse, recommendations);
        }

        // 8. 處理 AI 回應
        String aiReason = extractAiReason(aiResponse);

        // 9. 回傳 API JSON
        System.out.println("準備回傳的數據:");
        System.out.println("- 用戶輸入: " + cleanedInput);
        System.out.println("- 心情描述: " + moodDescription);
        System.out.println("- AI 回應: " + (aiResponse != null ? aiResponse.substring(0, Math.min(50, aiResponse.length())) + "..." : "null"));
        System.out.println("- AI 理由: " + aiReason);
        System.out.println("- 推薦數量: " + recommendations.size());
        System.out.println("- 服務類型: " + aiResult.getServiceType());
        System.out.println("- Bedrock 可用: " + aiResult.isBedrockAvailable());

        return new RecommendationResponse(cleanedInput, moodDescription, aiResponse, aiReason, recommendations, aiResult.getServiceType(), aiResult.isBedrockAvailable());

    } catch (Exception e) {
        return RecommendationResponse.error("推薦系統發生錯誤:" + e.getMessage());
    }
}

  1. Guardrails 過濾:首先呼叫 ContentFilterService,過濾使用者輸入,避免不當內容,並取得清理後的文字。
  2. 心情判斷:利用 MoodDetectionService 分析清理後的輸入,判斷使用者當下心情(如開心、疲憊、放鬆等),並取得心情描述。
  3. 取得使用者偏好:如果有登入,可以透過資料庫,根據 username 查詢使用者,取得偏好字串與收藏飲品,作為推薦參考。
  4. 生成 AI 推薦 Prompt:將使用者輸入、心情描述、偏好等資訊,組合成 prompt,傳給 AI(Bedrock Nova)。
  5. AI 產生推薦清單:呼叫 BedrockAIService,取得 AI 回應(推薦飲品及理由),並解析服務類型資訊。
  6. 菜單比對與推薦理由增強:將 AI 回應的飲品名稱與本地菜單比對,計算匹配分數,並根據心情與飲品特色增強推薦理由。若 AI 回應不足,會用智能匹配或備用推薦補充。
  7. 儲存推薦紀錄:將推薦結果、理由、使用者輸入等資訊存入資料庫,方便日後查詢。
  8. 處理 AI 回應:用 extractAiReason 處理 AI 回應,提取描述理由。
  9. 回傳 API JSON:最後回傳 RecommendationResponse,包含所有欄位(用戶輸入、心情、AI 回應、AI 理由、推薦清單、服務類型、Bedrock 可用性等)。

讓程式碼經由此服務進行多層次比對、個人化推薦與錯誤容錯,確保即使 AI 回應不足,也能給出合理建議。


上一篇
【Day24】AI Agent 魔法詠唱 - BedrockAI Service
系列文
跟 AI Agent 變成好朋友25
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言