Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions RAGManager/app/agents/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ def create_agent_graph() -> StateGraph:
Create and configure the LangGraph agent graph.

The graph implements the following flow:
1. START -> agent_host (Nodo 1) - Prepares state, no DB operations
1. START -> agent_host (Nodo 1) - Prepares state and retrieves chat history
2. agent_host -> guard_inicial (Nodo 2) - Validates for malicious content
3. guard_inicial -> [conditional]:
- malicious -> fallback_inicial -> END (stops processing, no DB save)
- malicious -> fallback_inicial -> END (stops processing, chat history available)
- continue -> parafraseo (Nodo 4)
4. parafraseo -> Saves message to DB, retrieves chat history, paraphrases
4. parafraseo -> Saves message to DB and paraphrases using chat history
5. parafraseo -> retriever (Nodo 5) - Retrieves relevant chunks from vector DB
6. retriever -> context_builder (Nodo 6) - Builds enriched query and generates response
7. context_builder -> guard_final (Nodo 8) - Validates response for risky content
Expand Down
64 changes: 50 additions & 14 deletions RAGManager/app/agents/nodes/agent_host.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
"""Nodo 1: Agent Host - Entry point that prepares initial state."""

import logging
from uuid import UUID

from app.agents.state import AgentState
from app.core.database_connection import SessionLocal
from app.services.chat import get_chat_history

logger = logging.getLogger(__name__)

Expand All @@ -14,16 +17,17 @@ def agent_host(state: AgentState) -> AgentState:
This node:
1. Receives the initial prompt and optional chat_session_id
2. Extracts the prompt from messages
3. Prepares state for validation (no DB operations yet)
3. Retrieves chat history if session_id is provided
4. Prepares state with context for the entire flow

Note: Chat history retrieval and message saving is deferred to parafraseo
node to ensure malicious messages are not saved to the database.
Note: Chat history is retrieved here (not in parafraseo) so it's available
throughout the entire flow, regardless of which path is taken (normal or fallback).

Args:
state: Agent state containing the user prompt and optional chat_session_id

Returns:
Updated state with prompt and initial_context set (no DB operations)
Updated state with prompt, chat_messages, and initial_context set
"""
updated_state = state.copy()

Expand All @@ -32,18 +36,50 @@ def agent_host(state: AgentState) -> AgentState:
last_message = messages[-1] if messages else None
prompt = last_message.content if last_message else ""

# Validate user_id is provided
user_id = state.get("user_id")
if not user_id:
logger.error("user_id is required in state but was not provided")
updated_state["error_message"] = "user_id is required"
return updated_state

# Set prompt and initial context (no DB operations)
# Set prompt and initial context
updated_state["prompt"] = prompt
updated_state["initial_context"] = prompt
updated_state["chat_messages"] = None # Will be set in parafraseo after validation

logger.debug("Agent host prepared state for validation (no DB operations)")
# Retrieve chat history if session exists
chat_session_id = state.get("chat_session_id")

if chat_session_id:
try:
# Convert to UUID if string
session_uuid = UUID(chat_session_id) if isinstance(chat_session_id, str) else chat_session_id

db = SessionLocal()
try:
# Get chat history from database
chat_messages = get_chat_history(db, session_uuid)

# Convert SQLAlchemy models to dicts for state
updated_state["chat_messages"] = [
{
"id": msg.id,
"sender": msg.sender,
"message": msg.message,
"created_at": msg.created_at.isoformat() if msg.created_at else None,
}
for msg in chat_messages
]

logger.info(f"Retrieved {len(chat_messages)} messages for session {session_uuid}")
finally:
db.close()

except ValueError as e:
# Session doesn't exist - this is okay for new sessions
logger.info(f"Chat session not found (likely new session): {e}")
updated_state["chat_messages"] = []
except Exception as e:
logger.error(f"Error retrieving chat history: {e}", exc_info=True)
updated_state["chat_messages"] = []
else:
# No session ID provided - new conversation
logger.info("No chat_session_id provided - starting new conversation")
updated_state["chat_messages"] = []

logger.debug(f"Agent host prepared state with {len(updated_state.get('chat_messages', []))} chat messages")

return updated_state
44 changes: 15 additions & 29 deletions RAGManager/app/agents/nodes/parafraseo.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Nodo 4: Parafraseo - Saves message, retrieves chat history, and paraphrases user input."""
"""Nodo 4: Parafraseo - Saves message and paraphrases user input using chat history."""

import json
import logging
Expand All @@ -14,21 +14,22 @@

def parafraseo(state: AgentState) -> AgentState:
"""
Parafraseo node - Saves message to DB, retrieves chat history, and paraphrases user input.
Parafraseo node - Saves message to DB and paraphrases user input using chat history.

This node:
1. Receives a validated user message (after guard_inicial validation)
2. Saves the user's message to the chat session in PostgreSQL (endpoint 1 - placeholder)
3. Retrieves the last 10 messages of the conversation (endpoint 2 - placeholder)
4. Uses the last message to understand user's intentions and the remaining 9 (older) messages as context
2. Saves the user's message to the chat session in PostgreSQL (TODO - placeholder)
3. Uses chat history (already retrieved by agent_host) as context
4. Uses the last message to understand user's intentions and chat history as context
5. Sends to LLM with instructions to return 3 differently phrased statements that encapsulate
the user's intentions according to the last message and chat history

Args:
state: Agent state containing validated user message, chat_session_id, and user_id
state: Agent state containing validated user message, chat_messages (from agent_host),
chat_session_id, and user_id

Returns:
Updated state with chat_messages, paraphrased_text, and paraphrased_statements set
Updated state with paraphrased_text and paraphrased_statements set
"""
updated_state = state.copy()

Expand All @@ -43,31 +44,16 @@ def parafraseo(state: AgentState) -> AgentState:
last_user_message = messages[-1]
user_message_content = last_user_message.content if hasattr(last_user_message, 'content') else str(last_user_message)

# TODO: Endpoint 1 - Save message to PostgreSQL database according to chat session
# TODO: Save message to PostgreSQL database according to chat session
# This should:
# 1. Call an endpoint (not yet developed) that:
# - Saves the current user message to the chat session in PostgreSQL
# - Uses chat_session_id and user_id from state
# - Returns success/failure status
# 2. Handle errors appropriately (session not found, permission denied, etc.)
logger.info("Endpoint 1 (save message to DB) not yet implemented - skipping")

# TODO: Endpoint 2 - Retrieve last 10 messages of the conversation
# This should:
# 1. Call an endpoint (not yet developed) that:
# - Retrieves the last 10 messages for the chat session
# - Returns a list of message dictionaries with structure: [{"sender": "user|assistant|system", "message": "...", "created_at": "..."}, ...]
# - Messages should be ordered from oldest to newest (or newest to oldest, depending on API design)
# 2. Update state with chat_messages from the endpoint response
# 1. Call a service or endpoint to save the current user message to the chat session
# 2. Use chat_session_id from state
# 3. Handle errors appropriately (session not found, permission denied, etc.)
logger.info("Message save to DB not yet implemented - skipping")

# Placeholder: For now, we'll simulate chat history with just the current message
# Once the endpoint is implemented, replace this with the actual endpoint call
chat_messages = [
{"sender": "user", "message": user_message_content, "created_at": "2025-01-01T00:00:00"}
]
updated_state["chat_messages"] = chat_messages
logger.warning("Endpoint 2 (retrieve chat history) not yet implemented - using current message only")
# Get chat history from state (already retrieved by agent_host)
chat_messages = state.get("chat_messages", [])
logger.info(f"Using {len(chat_messages)} chat messages from state (retrieved by agent_host)")

# Process chat history: last message (intentions) + 9 older messages (context)
# The last message is the most recent one (for understanding intentions)
Expand Down
Loading