Edith Choque Chura
Santiago Amaya
Un buen agente conversacional necesita memoria confiable. Aquí verás cómo LangGraph integra el historial en el estado, cómo usar los tipos de mensaje de LangChain y cómo evitar errores comunes en Python al concatenar listas. También conocerás el messages stage para agregar mensajes sin sobrescribir el historial y probarlo en la interfaz de debug.
¿Cómo estructurar el historial de mensajes en LangGraph?
Gestionar el contexto es clave para que la IA responda bien. LangChain ofrece una API de mensajes y LangGraph incorpora el historial como parte del estado compartido. Así, cada nodo conoce la conversación y responde según el rol del mensaje.
¿Qué tipos de mensajes existen y para qué sirven?
Ejemplo mínimo en Python:
# Importar clases de mensajes desde Landchain core (según el proyecto). from landchain_core.messages import AIMessage, HumanMessage, SystemMessage # nombres referenciales ai_msg = AIMessage(content="Hola, ¿en qué te ayudo?") print(ai_msg.text) # Propiedad mencionada para extraer el texto. human_msg = HumanMessage(content="Hola, soy Nicolás.")
¿Cómo imprimir y depurar el historial con prettyprint?
Cada mensaje expone un formato legible con prettyprint.
Útil para inspeccionar rápido el estado de la conversación.
history = [ai_msg, human_msg] for msg in history: msg.prettyprint() # Muestra rol y contenido de cada mensaje.
¿Cómo concatenar listas en Python sin errores?
Usa el operador + entre listas. Siempre listas.
Evita sumar un elemento suelto. Envuélvelo en una lista.
Patrón correcto para agregar al historial: lista + [nuevo_mensaje].
history = [human_msg] new_ai = AIMessage(content="Entendido.")
Correcto: concatenas listas.
history = history + [new_ai]
Incorrecto: no puedes sumar un solo objeto directamente.
history = history + new_ai # Esto daría error.
¿Cómo gestionar el estado compartido con messages stage?
El messages stage de LangGraph estandariza la gestión del historial: concatena nuevos mensajes sin reemplazar la lista existente. Funciona como memoria compartida entre nodos, con un protocolo de agregado eficiente.
¿Cómo definir el estado con la key messages?
El estado incluye la clave messages con una lista de mensajes.
Puedes tiparlo con base message o any message, o usar directamente el messages stage para abstraer la lógica de agregado.
Al retornar, solo envía lo nuevo a concatenar; el messages stage lo agrega al final.
Importar messages stage (según tu estructura de proyecto).
from langgraf.state import messages_stage # Referencial
from langchain_core.messages import AIMessage
def node_logic(state): respuesta = AIMessage(content="Hello") # Solo retorna lo nuevo; el messages stage concatena con el historial. return { "messages": [respuesta] }
¿Cómo reaccionar a entradas y agregar respuestas de la IA?
Lógica ejemplo: si no hay customer name, actualiza esa parte del estado. Si existe, agrega un AI message al historial.
En la interfaz de debug puedes inyectar mensajes iniciales: human message, AI message, tool, function, chat, etc.
El messages stage garantiza que siempre recibes un array, así puedes hacer get("messages") con confianza.
def simple_node(state): customer = state.get("customer_name")
if not customer: # Actualiza solo el nombre del cliente y no toca el historial. return {"customer_name": "Nicolás Molina"} # Si ya hay customer name, agrega una respuesta de la IA al historial. return { "messages": [AIMessage(content="Hola, ¿en qué más te ayudo?")] }
Prueba en debug: si envías un human message inicial (por ejemplo, "Hola, soy Nicolás"), verás que entra al estado y luego la IA concatena su respuesta sin borrar lo anterior.
¿Qué estrategias de contexto y tokens puedes aplicar?
Administrar el historial impacta costos y calidad. Puedes combinar técnicas según el caso.
¿Te gustaría ver más patrones de estado o ejemplos de tool message integrados? Comparte tu caso y continuamos la conversación.
Edith Choque Chura
Santiago Amaya
edgardo ponce
edgardo ponce
Nicolas Molina
ProfesorSantiago Amaya
Jhon Alejandro Insuasti Mosquera
Santiago Amaya
Andres Trujillo
Jhonatan Estiven Becerra Pedrozo
En el contexto de la gestión de historial de mensajes en LangGraph, un "grafo" se refiere a una estructura de datos que representa nodos y conexiones entre ellos. En este caso, cada nodo puede representar un estado o un mensaje dentro de una conversación. Los grafos permiten gestionar la interacción entre diferentes mensajes y estados, facilitando que un agente converse de manera más efectiva al tener en cuenta el historial de la conversación. Esto es fundamental para mantener una experiencia de usuario coherente y rica en contextos.
creo que seria mejor pensar en un nodo como una interacción de cierto tipo ya sea una interacción con un humano, un llm o una función y el grafo es el flujo de trabajo del output de dicha interacción, estos grafos usan el TypeDict como la memoria compartida y portador de información entre cada edge
El ejemplo me resultó un poco confuso y no me queda muy claro cómo se utiliza el historial. Incluso repitiendo esa parte varias veces, visualmente no logro identificar dónde se muestra. Creo que con un poco más de claridad al mostrarlo, sería mucho más fácil de entender.
le pedi a la ia un ejemplo para que lo pueda ver mas claro y me dio esto:
from langgraph.graph import MessagesState, StateGraph, START, END
from langchain_core.messages import HumanMessage, AIMessage
# Estado que hereda de MessagesState para tener historial automático
class State(MessagesState):
contador_interacciones: int = 0
def chatbot_node(state: State):
"""
Este nodo demuestra cómo trabajar con el historial de mensajes.
MessagesState mantiene automáticamente una lista de mensajes en state["messages"]
"""
# Acceder al historial completo
historial = state["messages"]
# Obtener el último mensaje del usuario
ultimo_mensaje = historial[-1] if historial else None
# Contar interacciones
nuevo_contador = state.get("contador_interacciones", 0) + 1
# Crear respuesta basada en el historial
if nuevo_contador == 1:
respuesta = AIMessage(content="¡Hola! Soy tu asistente. ¿En qué puedo ayudarte?")
elif nuevo_contador == 2:
respuesta = AIMessage(
content=f"Veo que dijiste: '{ultimo_mensaje.content}'. ¿Algo más?"
)
else:
num_mensajes = len(historial)
respuesta = AIMessage(
content=f"Llevamos {num_mensajes} mensajes en total. El historial se mantiene automáticamente."
)
# Retornar el nuevo mensaje (se agrega automáticamente al historial)
return {
"messages": [respuesta],
"contador_interacciones": nuevo_contador
}
# Construir el grafo
builder = StateGraph(State)
builder.add_node("chatbot", chatbot_node)
builder.add_edge(START, "chatbot")
builder.add_edge("chatbot", END)
agent = builder.compile()
Visualmente, no aparece en ningún lado los mensajes quedan en la memoria compartida de cada uno de los nodos y es la lista completa de mensajes en una conversación.
Recuerda que hay varios tipos de mensajes, en este tipo de conversaciones lo más común sería el mensaje del usuario (HummanMessage) y el mensaje de la IA (IAMessagge) pero existen otros tipos de mensajes como las ToolMessage que también quedan como parte del historial de la conversación.
Comprendiendo el "Graph State" en LangGraph (Python y LLMs)
Quiero compartir la manera en la que comprendí el Graph State, un concepto que considero vital al trabajar con LangGraph.
Básicamente, el Graph State es una estructura de datos compartida (comúnmente un TypedDict en Python) que representa la instantánea actual de toda la aplicación en un momento dado. Actúa como la memoria central o contexto compartido que viaja a través de los distintos nodos del flujo de trabajo.
Imagina que tienes un equipo de trabajo: un programador humano y tres agentes de IA, cada uno especializado en una tarea específica (por ejemplo, planificación, codificación y pruebas). Usamos el Graph State para manejar el flujo de trabajo y la comunicación entre estos "nodos" (agentes o funciones).
Funcionamiento clave:
reducer functions) que especifican cómo combinar la información nueva con la existente (por ejemplo, sobrescribir un valor o añadir elementos a una lista).clave: valor en el estado, puedes controlar la lógica condicional del grafo, decidiendo qué nodo debe ejecutarse a continuación (enrutamiento inteligente).En resumen, el Graph State es el sistema de memoria que permite a los agentes mantener un contexto coherente y coordinar tareas complejas a lo largo de un flujo de ejecución dinámico.key: values vas haciendo el manejo de versiones del flujo de trabajo, esto lo podrias programar de manera tal que se corra n veces hasta lograr una tarea en especifico o completar cierta cantidad de bucles
Para tener en cuenta que para poder testear el ejemplo de imprimir el mensaje, o llamas la funcion o imprimes
from langchain_core.messages import AIMessage, SystemMessage, ToolMessage ai_msg = AIMessage(content="Message from the AI") ai_msg.text() print(ai_msg.text)
Quiero dejar un projecto para una competición de kaggle que hice con langraph con la cual logre un silver medal usando ell api de google gemini 2.0 ....
Tambien comparto un video que te ayudara a profundizar un poco en llms y en un google capstone project en el que participe con un ingles bastante roto :D sobre AI generativa recomiendo bastante realizar un propio projecto o participar en una competencia de kaggle usando langgraph y la version gratuita de google para experimentar y jugar con llms configuration and langraph flow building
por ultimo supongo que lanzar un chat bot a production seria lo mejor de esto.... Tambien es bastante util apoyarse en llms... en mi caso tuve que comprender bastante sobre langchain pues chat gpt o llama o gemini de hace 6 meses no fue tan eficiente sin embargo me gui multiples veces para darme cuenta de muchas cosas sobre langgraph asi que puedes hacer tu propio profesor de ingles, o de python o incluso puedes hacer un rag para hacer llm especialista en documentaion sobre un service de tu empresa
Bueno entonces existen:
from langchain_core.messages import AIMessage, HumanMessage
AIMessage se encarga de los mensajes manejados por la AIHumanMessage se encarga de los mensajes manejados por el humanoCon esto podemos crear y manejar el historial de conversaciones usando la memoria de langGraph.
Ahora algo importante es, el proyecto no me estaba retornando la conversación que estabamos usando:
ai_message = AIMessage(content = "Hello, how can I help you today?") return { "messages": [ai_message] }
Pero esto se debia a que el property messages estaba escrito como message, entonces pilas que deben escribirlo bien como messages
Estas son las cosas que me hace titilar un ojo de python jajaja
No existe un text en la estructura de datos. Ah! pero si imprimes text?
Lo que venden como hermoso de python, la "sencilles", lo hace mas magico = cosas sin estructura o que no siguen una logica