Add RAG client
This commit is contained in:
154
src/main/java/com/example/mapper/rag/RagRequestMapper.java
Normal file
154
src/main/java/com/example/mapper/rag/RagRequestMapper.java
Normal 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;
|
||||
}
|
||||
}
|
||||
73
src/main/java/com/example/mapper/rag/RagResponseMapper.java
Normal file
73
src/main/java/com/example/mapper/rag/RagResponseMapper.java
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user