Add RAG client

This commit is contained in:
2026-02-22 22:45:47 +00:00
parent da95a64fb7
commit 20df3ab956
189 changed files with 10690 additions and 31 deletions

View File

@@ -0,0 +1,154 @@
/*
* 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;
}
}

View File

@@ -0,0 +1,73 @@
/*
* 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.DetectIntentResponseDTO;
import com.example.dto.dialogflow.conversation.QueryResultDTO;
import com.example.dto.rag.RagQueryResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.Collections;
import java.util.Map;
import java.util.UUID;
/**
* Mapper component responsible for converting RAG API responses to DetectIntentResponseDTO.
* This adapter ensures the response structure matches what the rest of the application expects.
*/
@Component
public class RagResponseMapper {
private static final Logger logger = LoggerFactory.getLogger(RagResponseMapper.class);
/**
* Maps a RagQueryResponse to a DetectIntentResponseDTO.
* Preserves the existing response structure expected by the rest of the application.
*
* @param ragResponse The response from the RAG server
* @param sessionId The session ID (for logging purposes)
* @return A DetectIntentResponseDTO matching the expected structure
*/
public DetectIntentResponseDTO mapFromRagResponse(RagQueryResponse ragResponse, String sessionId) {
logger.info("Mapping RAG response to DetectIntentResponseDTO for session: {}", sessionId);
// Use RAG's response_id if available, otherwise generate one
String responseId = ragResponse.responseId() != null && !ragResponse.responseId().isBlank()
? ragResponse.responseId()
: "rag-" + UUID.randomUUID().toString();
// Extract response text
String responseText = ragResponse.responseText() != null
? ragResponse.responseText()
: "";
if (responseText.isBlank()) {
logger.warn("RAG returned empty response text for session: {}", sessionId);
}
// Extract parameters (can be null or empty)
Map<String, Object> parameters = ragResponse.parameters() != null
? ragResponse.parameters()
: Collections.emptyMap();
// Log confidence if available
if (ragResponse.confidence() != null) {
logger.debug("RAG response confidence: {} for session: {}", ragResponse.confidence(), sessionId);
}
// Create QueryResultDTO with response text and parameters
QueryResultDTO queryResult = new QueryResultDTO(responseText, parameters);
// Create DetectIntentResponseDTO (quickReplies is null for now)
DetectIntentResponseDTO response = new DetectIntentResponseDTO(responseId, queryResult, null);
logger.info("Successfully mapped RAG response for session: {}. Response ID: {}", sessionId, responseId);
return response;
}
}