116 lines
5.0 KiB
Java
116 lines
5.0 KiB
Java
/*
|
|
* Copyright 2025 Google. This software is provided as-is, without warranty or representation for any use or purpose.
|
|
* Your use of it is subject to your agreement with Google.
|
|
*/
|
|
package com.example.service.base;
|
|
|
|
import com.example.service.notification.MemoryStoreNotificationService;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
import org.springframework.core.io.ClassPathResource;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.util.FileCopyUtils;
|
|
import jakarta.annotation.PostConstruct;
|
|
import java.io.IOException;
|
|
import java.io.Reader;
|
|
import java.io.InputStreamReader;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.util.Objects;
|
|
|
|
@Service
|
|
public class NotificationContextResolver {
|
|
|
|
private static final Logger logger = LoggerFactory.getLogger(NotificationContextResolver.class);
|
|
private final GeminiClientService geminiService;
|
|
|
|
@Value("${notificationcontext.geminimodel:gemini-2.0-flash-001}")
|
|
private String geminiModelNameResolver;
|
|
|
|
@Value("${notificationcontext.temperature:0.1f}")
|
|
private Float resolverTemperature;
|
|
|
|
@Value("${notificationcontext.maxOutputTokens:1024}")
|
|
private Integer resolverMaxOutputTokens;
|
|
|
|
@Value("${notificationcontext.topP:0.1f}")
|
|
private Float resolverTopP;
|
|
|
|
@Value("${notificationcontext.prompt:prompts/notification_context_resolver.txt}")
|
|
private String promptFilePath;
|
|
|
|
public static final String CATEGORY_DIALOGFLOW = "DIALOGFLOW";
|
|
|
|
private String promptTemplate;
|
|
|
|
public NotificationContextResolver(GeminiClientService geminiService, MemoryStoreNotificationService memoryStoreNotificationService) {
|
|
this.geminiService = Objects.requireNonNull(geminiService,
|
|
"GeminiClientService cannot be null for NotificationContextResolver.");
|
|
}
|
|
|
|
@PostConstruct
|
|
public void loadPromptTemplate() {
|
|
try {
|
|
ClassPathResource resource = new ClassPathResource(promptFilePath);
|
|
try (Reader reader = new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8)) {
|
|
this.promptTemplate = FileCopyUtils.copyToString(reader);
|
|
}
|
|
logger.info("Successfully loaded prompt template from '{}'.", promptFilePath);
|
|
} catch (IOException e) {
|
|
logger.error("Failed to load prompt template from '{}'. Please ensure the file exists.", promptFilePath, e);
|
|
throw new IllegalStateException("Could not load prompt template.", e);
|
|
}
|
|
}
|
|
|
|
public String resolveContext(String queryInputText, String notificationsJson, String conversationJson,
|
|
String metadata, String userId, String sessionId, String userPhoneNumber) {
|
|
logger.debug("resolveContext -> queryInputText: {}, notificationsJson: {}, conversationJson: {}, metadata: {}", queryInputText, notificationsJson, conversationJson, metadata);
|
|
if (queryInputText == null || queryInputText.isBlank()) {
|
|
logger.warn("Query input text for context resolution is null or blank. Returning {}.", CATEGORY_DIALOGFLOW);
|
|
return CATEGORY_DIALOGFLOW;
|
|
}
|
|
|
|
String notificationContent = (notificationsJson != null && !notificationsJson.isBlank()) ? notificationsJson
|
|
: "No metadata in notification.";
|
|
|
|
String conversationHistory = (conversationJson != null && !conversationJson.isBlank()) ? conversationJson
|
|
: "No conversation history.";
|
|
|
|
String contextPrompt = String.format(
|
|
this.promptTemplate,
|
|
conversationHistory,
|
|
notificationContent,
|
|
metadata,
|
|
queryInputText);
|
|
|
|
logger.debug("Sending context resolution request to Gemini for input (first 100 chars): '{}'...",
|
|
queryInputText.substring(0, Math.min(queryInputText.length(), 100)));
|
|
|
|
try {
|
|
String geminiResponse = geminiService.generateContent(
|
|
contextPrompt,
|
|
resolverTemperature,
|
|
resolverMaxOutputTokens,
|
|
geminiModelNameResolver,
|
|
resolverTopP);
|
|
|
|
if (geminiResponse != null && !geminiResponse.isBlank()) {
|
|
if (geminiResponse.trim().equalsIgnoreCase(CATEGORY_DIALOGFLOW)) {
|
|
logger.info("Resolved to {}. Input: '{}'", CATEGORY_DIALOGFLOW, queryInputText);
|
|
return CATEGORY_DIALOGFLOW;
|
|
} else {
|
|
logger.info("Resolved to a specific response. Input: '{}'", queryInputText);
|
|
return geminiResponse;
|
|
}
|
|
} else {
|
|
logger.warn("Gemini returned a null or blank response. Input: '{}'. Returning {}.",
|
|
queryInputText, CATEGORY_DIALOGFLOW);
|
|
return CATEGORY_DIALOGFLOW;
|
|
}
|
|
} catch (Exception e) {
|
|
logger.error("An error occurred during Gemini content generation for context resolution.", e);
|
|
return CATEGORY_DIALOGFLOW;
|
|
}
|
|
}
|
|
}
|