⚡ Construir agentes lingüísticos como gráficos ⚡
Nota
¿Busca la versión JS? Haga clic aquí (documentos JS).
LangGraph es una biblioteca para crear aplicaciones multiactor con estado con LLM, que se utiliza para crear flujos de trabajo de agentes y multiagentes. En comparación con otros marcos LLM, ofrece estos beneficios principales: ciclos, controlabilidad y persistencia. LangGraph le permite definir flujos que involucran ciclos, esenciales para la mayoría de las arquitecturas agentes, diferenciándolo de las soluciones basadas en DAG. Como marco de muy bajo nivel, proporciona un control detallado sobre el flujo y el estado de su aplicación, lo cual es crucial para crear agentes confiables. Además, LangGraph incluye persistencia incorporada, lo que permite funciones avanzadas de memoria y de interacción humana.
LangGraph está inspirado en Pregel y Apache Beam. La interfaz pública se inspira en NetworkX. LangGraph fue creado por LangChain Inc, los creadores de LangChain, pero se puede usar sin LangChain.
LangGraph Platform es una infraestructura para implementar agentes LangGraph. Es una solución comercial para implementar aplicaciones agentes en producción, construida sobre el marco LangGraph de código abierto. La plataforma LangGraph consta de varios componentes que trabajan juntos para respaldar el desarrollo, implementación, depuración y monitoreo de aplicaciones LangGraph: LangGraph Server (API), LangGraph SDK (clientes para las API), LangGraph CLI (herramienta de línea de comandos para construir el servidor). ), LangGraph Studio (UI/depurador),
Para obtener más información sobre LangGraph, consulte nuestro primer curso de LangChain Academy, Introducción a LangGraph , disponible de forma gratuita aquí.
LangGraph Platform es una solución comercial para implementar aplicaciones agentes en producción, construida sobre el marco LangGraph de código abierto. A continuación, se muestran algunos problemas comunes que surgen en implementaciones complejas y que LangGraph Platform aborda:
pip install -U langgraph
Uno de los conceptos centrales de LangGraph es el estado. Cada ejecución del gráfico crea un estado que se pasa entre los nodos del gráfico a medida que se ejecutan, y cada nodo actualiza este estado interno con su valor de retorno después de la ejecución. La forma en que el gráfico actualiza su estado interno se define mediante el tipo de gráfico elegido o una función personalizada.
Echemos un vistazo a un ejemplo sencillo de un agente que puede utilizar una herramienta de búsqueda.
pip install langchain-anthropic
export ANTHROPIC_API_KEY=sk-...
Opcionalmente, podemos configurar LangSmith para obtener la mejor observabilidad de su clase.
export LANGSMITH_TRACING=true
export LANGSMITH_API_KEY=lsv2_sk_...
from typing import Annotated , Literal , TypedDict
from langchain_core . messages import HumanMessage
from langchain_anthropic import ChatAnthropic
from langchain_core . tools import tool
from langgraph . checkpoint . memory import MemorySaver
from langgraph . graph import END , START , StateGraph , MessagesState
from langgraph . prebuilt import ToolNode
# Define the tools for the agent to use
@ tool
def search ( query : str ):
"""Call to surf the web."""
# This is a placeholder, but don't tell the LLM that...
if "sf" in query . lower () or "san francisco" in query . lower ():
return "It's 60 degrees and foggy."
return "It's 90 degrees and sunny."
tools = [ search ]
tool_node = ToolNode ( tools )
model = ChatAnthropic ( model = "claude-3-5-sonnet-20240620" , temperature = 0 ). bind_tools ( tools )
# Define the function that determines whether to continue or not
def should_continue ( state : MessagesState ) -> Literal [ "tools" , END ]:
messages = state [ 'messages' ]
last_message = messages [ - 1 ]
# If the LLM makes a tool call, then we route to the "tools" node
if last_message . tool_calls :
return "tools"
# Otherwise, we stop (reply to the user)
return END
# Define the function that calls the model
def call_model ( state : MessagesState ):
messages = state [ 'messages' ]
response = model . invoke ( messages )
# We return a list, because this will get added to the existing list
return { "messages" : [ response ]}
# Define a new graph
workflow = StateGraph ( MessagesState )
# Define the two nodes we will cycle between
workflow . add_node ( "agent" , call_model )
workflow . add_node ( "tools" , tool_node )
# Set the entrypoint as `agent`
# This means that this node is the first one called
workflow . add_edge ( START , "agent" )
# We now add a conditional edge
workflow . add_conditional_edges (
# First, we define the start node. We use `agent`.
# This means these are the edges taken after the `agent` node is called.
"agent" ,
# Next, we pass in the function that will determine which node is called next.
should_continue ,
)
# We now add a normal edge from `tools` to `agent`.
# This means that after `tools` is called, `agent` node is called next.
workflow . add_edge ( "tools" , 'agent' )
# Initialize memory to persist state between graph runs
checkpointer = MemorySaver ()
# Finally, we compile it!
# This compiles it into a LangChain Runnable,
# meaning you can use it as you would any other runnable.
# Note that we're (optionally) passing the memory when compiling the graph
app = workflow . compile ( checkpointer = checkpointer )
# Use the Runnable
final_state = app . invoke (
{ "messages" : [ HumanMessage ( content = "what is the weather in sf" )]},
config = { "configurable" : { "thread_id" : 42 }}
)
final_state [ "messages" ][ - 1 ]. content
"Based on the search results, I can tell you that the current weather in San Francisco is:nnTemperature: 60 degrees FahrenheitnConditions: FoggynnSan Francisco is known for its microclimates and frequent fog, especially during the summer months. The temperature of 60°F (about 15.5°C) is quite typical for the city, which tends to have mild temperatures year-round. The fog, often referred to as "Karl the Fog" by locals, is a characteristic feature of San Francisco's weather, particularly in the mornings and evenings.nnIs there anything else you'd like to know about the weather in San Francisco or any other location?"
Ahora, cuando pasamos el mismo "thread_id"
, el contexto de la conversación se conserva mediante el estado guardado (es decir, la lista almacenada de mensajes).
final_state = app . invoke (
{ "messages" : [ HumanMessage ( content = "what about ny" )]},
config = { "configurable" : { "thread_id" : 42 }}
)
final_state [ "messages" ][ - 1 ]. content
"Based on the search results, I can tell you that the current weather in New York City is:nnTemperature: 90 degrees Fahrenheit (approximately 32.2 degrees Celsius)nConditions: SunnynnThis weather is quite different from what we just saw in San Francisco. New York is experiencing much warmer temperatures right now. Here are a few points to note:nn1. The temperature of 90°F is quite hot, typical of summer weather in New York City.n2. The sunny conditions suggest clear skies, which is great for outdoor activities but also means it might feel even hotter due to direct sunlight.n3. This kind of weather in New York often comes with high humidity, which can make it feel even warmer than the actual temperature suggests.nnIt's interesting to see the stark contrast between San Francisco's mild, foggy weather and New York's hot, sunny conditions. This difference illustrates how varied weather can be across different parts of the United States, even on the same day.nnIs there anything else you'd like to know about the weather in New York or any other location?"
ChatAnthropic
como nuestro LLM. NOTA: debemos asegurarnos de que el modelo sepa que tiene estas herramientas disponibles para llamar. Podemos hacer esto convirtiendo las herramientas LangChain al formato para llamar a herramientas OpenAI usando el método .bind_tools()
.StateGraph
) pasando el esquema de estado (en nuestro caso MessagesState
)MessagesState
es un esquema de estado prediseñado que tiene un atributo: una lista de objetos Message
LangChain, así como lógica para fusionar las actualizaciones de cada nodo en el estado.Hay dos nodos principales que necesitamos:
agent
: responsable de decidir qué acciones (si las hay) tomar.tools
que invoca herramientas: si el agente decide realizar una acción, este nodo ejecutará esa acción. Primero, debemos establecer el punto de entrada para la ejecución del gráfico: el nodo agent
.
Luego definimos una arista normal y otra condicional. Borde condicional significa que el destino depende del contenido del estado del gráfico ( MessageState
). En nuestro caso, el destino no se conoce hasta que el agente (LLM) lo decide.
.invoke()
, .stream()
y .batch()
con sus entradas.MemorySaver
, un simple puntero de control en memoria. LangGraph agrega el mensaje de entrada al estado interno y luego pasa el estado al nodo de punto de entrada, "agent"
.
El nodo "agent"
se ejecuta invocando el modelo de chat.
El modelo de chat devuelve un AIMessage
. LangGraph agrega esto al estado.
Graph recorre los siguientes pasos hasta que no haya más tool_calls
en AIMessage
:
AIMessage
tiene tool_calls
, el nodo "tools"
se ejecuta"agent"
se ejecuta nuevamente y devuelve AIMessage
La ejecución avanza hasta el valor END
especial y genera el estado final. Y como resultado, obtenemos una lista de todos nuestros mensajes de chat como resultado.
Para obtener más información sobre cómo contribuir, consulte aquí.