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 回應不足,也能給出合理建議。