155 lines
6.2 KiB
Java
155 lines
6.2 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.mapper.rag;
|
|
|
|
import com.example.dto.dialogflow.base.DetectIntentRequestDTO;
|
|
import com.example.dto.dialogflow.conversation.QueryInputDTO;
|
|
import com.example.dto.rag.RagQueryRequest;
|
|
import com.example.dto.rag.RagQueryRequest.NotificationContext;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import org.springframework.stereotype.Component;
|
|
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
import java.util.Objects;
|
|
|
|
/**
|
|
* Mapper component responsible for converting DetectIntentRequestDTO to RAG API format.
|
|
* This adapter preserves the existing DTO structure while translating to the simpler RAG API.
|
|
*/
|
|
@Component
|
|
public class RagRequestMapper {
|
|
|
|
private static final Logger logger = LoggerFactory.getLogger(RagRequestMapper.class);
|
|
private static final String NOTIFICATION_PREFIX = "notification_po_";
|
|
private static final String NOTIFICATION_TEXT_PARAM = "notification_text";
|
|
|
|
/**
|
|
* Maps a DetectIntentRequestDTO to a RagQueryRequest.
|
|
* Extracts the phone number, text/event, and notification data from the existing structure.
|
|
*
|
|
* @param requestDto The existing DetectIntentRequestDTO
|
|
* @param sessionId The session ID (not used by RAG but kept for logging)
|
|
* @return A RagQueryRequest ready to send to the RAG server
|
|
*/
|
|
public RagQueryRequest mapToRagRequest(DetectIntentRequestDTO requestDto, String sessionId) {
|
|
Objects.requireNonNull(requestDto, "DetectIntentRequestDTO cannot be null");
|
|
|
|
logger.debug("Mapping DetectIntentRequestDTO to RagQueryRequest for session: {}", sessionId);
|
|
|
|
// Extract phone number from parameters
|
|
Map<String, Object> parameters = requestDto.queryParams() != null
|
|
? requestDto.queryParams().parameters()
|
|
: Map.of();
|
|
|
|
String phoneNumber = extractPhoneNumber(parameters);
|
|
if (phoneNumber == null || phoneNumber.isBlank()) {
|
|
logger.error("Phone number is required but not found in request parameters");
|
|
throw new IllegalArgumentException("Phone number is required in request parameters");
|
|
}
|
|
|
|
// Extract text or event from QueryInputDTO
|
|
QueryInputDTO queryInput = requestDto.queryInput();
|
|
String text = extractText(queryInput);
|
|
String languageCode = queryInput.languageCode();
|
|
|
|
// Determine request type and notification context
|
|
String type = determineRequestType(queryInput, parameters);
|
|
NotificationContext notificationContext = extractNotificationContext(parameters);
|
|
|
|
RagQueryRequest ragRequest = new RagQueryRequest(
|
|
phoneNumber,
|
|
text,
|
|
type,
|
|
notificationContext,
|
|
languageCode
|
|
);
|
|
|
|
logger.debug("Mapped RAG request: type={}, phoneNumber={}, hasNotification={}",
|
|
type, phoneNumber, notificationContext != null);
|
|
|
|
return ragRequest;
|
|
}
|
|
|
|
/**
|
|
* Extracts the phone number from request parameters.
|
|
*/
|
|
private String extractPhoneNumber(Map<String, Object> parameters) {
|
|
Object telefono = parameters.get("telefono");
|
|
if (telefono instanceof String) {
|
|
return (String) telefono;
|
|
}
|
|
logger.warn("Phone number (telefono) not found or not a string in parameters");
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Extracts text from QueryInputDTO (either text input or event).
|
|
* For events, we use the event name as the text.
|
|
*/
|
|
private String extractText(QueryInputDTO queryInput) {
|
|
if (queryInput.text() != null && queryInput.text().text() != null
|
|
&& !queryInput.text().text().trim().isEmpty()) {
|
|
return queryInput.text().text();
|
|
} else if (queryInput.event() != null && queryInput.event().event() != null
|
|
&& !queryInput.event().event().trim().isEmpty()) {
|
|
// For events (like "LLM_RESPONSE_PROCESSED"), use the event name
|
|
return queryInput.event().event();
|
|
} else {
|
|
logger.error("Query input must contain either text or event");
|
|
throw new IllegalArgumentException("Query input must contain either text or event");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Determines if this is a conversation or notification request.
|
|
* If notification parameters are present, it's a notification request.
|
|
*/
|
|
private String determineRequestType(QueryInputDTO queryInput, Map<String, Object> parameters) {
|
|
// Check if there are notification-prefixed parameters
|
|
boolean hasNotificationParams = parameters.keySet().stream()
|
|
.anyMatch(key -> key.startsWith(NOTIFICATION_PREFIX));
|
|
|
|
// Check if there's a notification_text parameter
|
|
boolean hasNotificationText = parameters.containsKey(NOTIFICATION_TEXT_PARAM);
|
|
|
|
// Check if the input is an event (notifications use events)
|
|
boolean isEvent = queryInput.event() != null && queryInput.event().event() != null;
|
|
|
|
if (hasNotificationParams || hasNotificationText ||
|
|
(isEvent && "notificacion".equals(queryInput.event().event()))) {
|
|
return "notification";
|
|
}
|
|
|
|
return "conversation";
|
|
}
|
|
|
|
/**
|
|
* Extracts notification context from parameters.
|
|
* Looks for notification_text and notification_po_* parameters.
|
|
*/
|
|
private NotificationContext extractNotificationContext(Map<String, Object> parameters) {
|
|
String notificationText = (String) parameters.get(NOTIFICATION_TEXT_PARAM);
|
|
|
|
// Extract all notification_po_* parameters and remove the prefix
|
|
Map<String, Object> notificationParams = new HashMap<>();
|
|
parameters.forEach((key, value) -> {
|
|
if (key.startsWith(NOTIFICATION_PREFIX)) {
|
|
String cleanKey = key.substring(NOTIFICATION_PREFIX.length());
|
|
notificationParams.put(cleanKey, value);
|
|
}
|
|
});
|
|
|
|
// Only create NotificationContext if we have notification data
|
|
if (notificationText != null || !notificationParams.isEmpty()) {
|
|
return new NotificationContext(notificationText, notificationParams);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|