.
This commit is contained in:
@@ -1,14 +1,7 @@
|
||||
"""
|
||||
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.
|
||||
|
||||
Conversation manager service - central orchestrator for conversations.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import uuid
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Any
|
||||
|
||||
from ..config import Settings
|
||||
from ..models import (
|
||||
@@ -21,14 +14,10 @@ from ..models import (
|
||||
TextInputDTO,
|
||||
QueryParamsDTO,
|
||||
)
|
||||
from ..utils import SessionIdGenerator
|
||||
from .dialogflow_client import DialogflowClientService
|
||||
from .redis_service import RedisService
|
||||
from .firestore_service import FirestoreService
|
||||
from .dlp_service import DLPService
|
||||
from .message_filter import MessageEntryFilter
|
||||
from .notification_context_resolver import NotificationContextResolver
|
||||
from .llm_response_tuner import LlmResponseTunerService
|
||||
from .rag_service import RAGService
|
||||
from .mappers import NotificationContextMapper, ConversationContextMapper
|
||||
from .quick_reply_content import QuickReplyContentService
|
||||
|
||||
@@ -62,23 +51,17 @@ class ConversationManagerService:
|
||||
def __init__(
|
||||
self,
|
||||
settings: Settings,
|
||||
dialogflow_client: DialogflowClientService,
|
||||
rag_service: RAGService,
|
||||
redis_service: RedisService,
|
||||
firestore_service: FirestoreService,
|
||||
dlp_service: DLPService,
|
||||
message_filter: MessageEntryFilter,
|
||||
notification_context_resolver: NotificationContextResolver,
|
||||
llm_response_tuner: LlmResponseTunerService,
|
||||
):
|
||||
"""Initialize conversation manager."""
|
||||
self.settings = settings
|
||||
self.dialogflow_client = dialogflow_client
|
||||
self.rag_service = rag_service
|
||||
self.redis_service = redis_service
|
||||
self.firestore_service = firestore_service
|
||||
self.dlp_service = dlp_service
|
||||
self.message_filter = message_filter
|
||||
self.notification_context_resolver = notification_context_resolver
|
||||
self.llm_response_tuner = llm_response_tuner
|
||||
|
||||
# Initialize mappers
|
||||
self.notification_mapper = NotificationContextMapper()
|
||||
@@ -117,18 +100,10 @@ class ConversationManagerService:
|
||||
request.mensaje,
|
||||
self.settings.dlp_template_complete_flow,
|
||||
)
|
||||
|
||||
obfuscated_request = ExternalConvRequestDTO(
|
||||
mensaje=obfuscated_message,
|
||||
usuario=request.usuario,
|
||||
canal=request.canal,
|
||||
tipo=request.tipo,
|
||||
pantalla_contexto=request.pantalla_contexto,
|
||||
)
|
||||
request.mensaje = obfuscated_message
|
||||
|
||||
# Step 2: Check for pantallaContexto in existing session
|
||||
telefono = request.usuario.telefono
|
||||
existing_session = await self.redis_service.get_session(telefono)
|
||||
existing_session = await self.redis_service.get_session(request.usuario.telefono)
|
||||
|
||||
if existing_session and existing_session.pantallaContexto:
|
||||
# Check if pantallaContexto is stale (10 minutes)
|
||||
@@ -137,16 +112,14 @@ class ConversationManagerService:
|
||||
f"Detected 'pantallaContexto' in session: {existing_session.pantallaContexto}. "
|
||||
f"Delegating to QuickReplies flow."
|
||||
)
|
||||
return await self._manage_quick_reply_conversation(
|
||||
obfuscated_request, existing_session
|
||||
)
|
||||
return await self._manage_quick_reply_conversation(request, existing_session)
|
||||
else:
|
||||
logger.info(
|
||||
"Detected STALE 'pantallaContexto'. Ignoring and proceeding with normal flow."
|
||||
)
|
||||
|
||||
# Step 3: Continue with standard conversation flow
|
||||
return await self._continue_managing_conversation(obfuscated_request)
|
||||
return await self._continue_managing_conversation(request)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error managing conversation: {str(e)}", exc_info=True)
|
||||
@@ -183,7 +156,10 @@ class ConversationManagerService:
|
||||
)
|
||||
|
||||
# Add pantallaContexto to parameters
|
||||
if dialogflow_request.query_params:
|
||||
if (
|
||||
dialogflow_request.query_params
|
||||
and dialogflow_request.query_params.parameters
|
||||
):
|
||||
dialogflow_request.query_params.parameters["pantalla_contexto"] = (
|
||||
session.pantallaContexto
|
||||
)
|
||||
@@ -395,9 +371,13 @@ class ConversationManagerService:
|
||||
dialogflow_request = self._build_dialogflow_request(
|
||||
request, new_session, request.mensaje
|
||||
)
|
||||
dialogflow_request.query_params.parameters[self.CONV_HISTORY_PARAM] = (
|
||||
conversation_history
|
||||
)
|
||||
if (
|
||||
dialogflow_request.query_params
|
||||
and dialogflow_request.query_params.parameters
|
||||
):
|
||||
dialogflow_request.query_params.parameters[self.CONV_HISTORY_PARAM] = (
|
||||
conversation_history
|
||||
)
|
||||
|
||||
return await self._process_dialogflow_request(
|
||||
new_session,
|
||||
@@ -409,7 +389,7 @@ class ConversationManagerService:
|
||||
async def _start_notification_conversation(
|
||||
self,
|
||||
request: ExternalConvRequestDTO,
|
||||
notification: any,
|
||||
notification: Any,
|
||||
session: ConversationSessionDTO,
|
||||
conversation_entries: list[ConversationEntryDTO],
|
||||
) -> DetectIntentResponseDTO:
|
||||
@@ -490,13 +470,23 @@ class ConversationManagerService:
|
||||
conversation_history = self.conversation_mapper.to_text_with_limits(
|
||||
session, firestore_entries
|
||||
)
|
||||
dialogflow_request.query_params.parameters[self.CONV_HISTORY_PARAM] = (
|
||||
conversation_history
|
||||
)
|
||||
if (
|
||||
dialogflow_request.query_params
|
||||
and dialogflow_request.query_params.parameters
|
||||
):
|
||||
dialogflow_request.query_params.parameters[
|
||||
self.CONV_HISTORY_PARAM
|
||||
] = conversation_history
|
||||
|
||||
# Always add notification parameters
|
||||
if notification.parametros:
|
||||
dialogflow_request.query_params.parameters.update(notification.parametros)
|
||||
if (
|
||||
notification.parametros
|
||||
and dialogflow_request.query_params
|
||||
and dialogflow_request.query_params.parameters
|
||||
):
|
||||
dialogflow_request.query_params.parameters.update(
|
||||
notification.parametros
|
||||
)
|
||||
|
||||
response = await self.dialogflow_client.detect_intent(
|
||||
session.sessionId, dialogflow_request
|
||||
@@ -579,9 +569,13 @@ class ConversationManagerService:
|
||||
dialogflow_request = self._build_dialogflow_request(
|
||||
request, new_session, request.mensaje
|
||||
)
|
||||
dialogflow_request.query_params.parameters[self.CONV_HISTORY_PARAM] = (
|
||||
conversation_history
|
||||
)
|
||||
if (
|
||||
dialogflow_request.query_params
|
||||
and dialogflow_request.query_params.parameters
|
||||
):
|
||||
dialogflow_request.query_params.parameters[self.CONV_HISTORY_PARAM] = (
|
||||
conversation_history
|
||||
)
|
||||
|
||||
return await self._process_dialogflow_request(
|
||||
new_session,
|
||||
@@ -720,12 +714,10 @@ class ConversationManagerService:
|
||||
|
||||
# Create conversation entry
|
||||
response_text = ""
|
||||
intent = None
|
||||
parameters = None
|
||||
|
||||
if response.queryResult:
|
||||
response_text = response.queryResult.text or ""
|
||||
intent = response.queryResult.intent
|
||||
response_text = response.queryResult.responseText or ""
|
||||
parameters = response.queryResult.parameters
|
||||
|
||||
user_entry = ConversationEntryDTO(
|
||||
@@ -734,7 +726,6 @@ class ConversationManagerService:
|
||||
timestamp=datetime.now(),
|
||||
text=user_message,
|
||||
parameters=None,
|
||||
intent=None,
|
||||
)
|
||||
|
||||
agent_entry = ConversationEntryDTO(
|
||||
@@ -743,7 +734,6 @@ class ConversationManagerService:
|
||||
timestamp=datetime.now(),
|
||||
text=response_text,
|
||||
parameters=parameters,
|
||||
intent=intent,
|
||||
)
|
||||
|
||||
# Save to Redis (fast, blocking)
|
||||
@@ -757,8 +747,12 @@ class ConversationManagerService:
|
||||
async def save_to_firestore():
|
||||
try:
|
||||
await self.firestore_service.save_session(updated_session)
|
||||
await self.firestore_service.save_entry(session.sessionId, user_entry)
|
||||
await self.firestore_service.save_entry(session.sessionId, agent_entry)
|
||||
await self.firestore_service.save_entry(
|
||||
session.sessionId, user_entry
|
||||
)
|
||||
await self.firestore_service.save_entry(
|
||||
session.sessionId, agent_entry
|
||||
)
|
||||
logger.debug(
|
||||
f"Asynchronously (Write-Back): Entry successfully saved to Firestore for session: {session.sessionId}"
|
||||
)
|
||||
@@ -800,8 +794,7 @@ class ConversationManagerService:
|
||||
type="CONVERSACION",
|
||||
timestamp=datetime.now(),
|
||||
text=user_message,
|
||||
parameters=notification.parametros,
|
||||
intent=None,
|
||||
parameters=None,
|
||||
)
|
||||
|
||||
llm_entry = ConversationEntryDTO(
|
||||
@@ -810,7 +803,6 @@ class ConversationManagerService:
|
||||
timestamp=datetime.now(),
|
||||
text=llm_response,
|
||||
parameters=None,
|
||||
intent=None,
|
||||
)
|
||||
|
||||
# Save to Redis (fast, blocking)
|
||||
@@ -824,8 +816,12 @@ class ConversationManagerService:
|
||||
async def save_to_firestore():
|
||||
try:
|
||||
await self.firestore_service.save_session(updated_session)
|
||||
await self.firestore_service.save_entry(session.sessionId, user_entry)
|
||||
await self.firestore_service.save_entry(session.sessionId, llm_entry)
|
||||
await self.firestore_service.save_entry(
|
||||
session.sessionId, user_entry
|
||||
)
|
||||
await self.firestore_service.save_entry(
|
||||
session.sessionId, llm_entry
|
||||
)
|
||||
logger.debug(
|
||||
f"Asynchronously (Write-Back): LLM entry successfully saved to Firestore for session: {session.sessionId}"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user