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());
    }
}
ContentFilterService,過濾使用者輸入,避免不當內容,並取得清理後的文字。MoodDetectionService 分析清理後的輸入,判斷使用者當下心情(如開心、疲憊、放鬆等),並取得心情描述。BedrockAIService,取得 AI 回應(推薦飲品及理由),並解析服務類型資訊。extractAiReason 處理 AI 回應,提取描述理由。RecommendationResponse,包含所有欄位(用戶輸入、心情、AI 回應、AI 理由、推薦清單、服務類型、Bedrock 可用性等)。讓程式碼經由此服務進行多層次比對、個人化推薦與錯誤處理,確保即使 AI 回應不足,也能給出合理建議。