Files
int-layer/src/main/java/com/example/mapper/rag/RagRequestMapper.java
2026-02-23 03:17:18 +00:00

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;
}
}