1. El problema de los LLM
Entonces tienes tu chatbot favorito y lo utilizas en tu trabajo diario para aumentar tu productividad. Puede traducir textos, escribir bonitos correos electrónicos, contar chistes, etc. Y luego llega el día en que tu colega se acerca a ti y te pregunta:
“¿Conoce el tipo de cambio actual entre USD y EUR? Me pregunto si debería vender mi EUR…”
Le preguntas a tu chatbot favorito y aparece la respuesta:
I am sorry, I cannot fulfill this request.
I do not have access to real-time information, including financial data
like exchange rates.
¿Cuál es el problema aquí?
El problema es que te has topado con una de las deficiencias de los LLM. Los modelos de lenguaje grande (LLM) son poderosos para resolver muchos tipos de problemas, como resolución de problemas, resumen de texto, generación, etc.
Sin embargo, están limitados por las siguientes limitaciones:
- Se congelan después del entrenamiento, lo que lleva a que el conocimiento se vuelva obsoleto.
- No pueden consultar ni modificar datos externos.
De la misma manera que usamos motores de búsqueda todos los días, leemos libros y documentos o consultamos bases de datos, lo ideal sería brindar este conocimiento a nuestro LLM para hacerlo más eficiente.
Afortunadamente, existe una manera de hacerlo: Herramientas y Agentes.
Los modelos fundamentales, a pesar de su impresionante generación de texto e imágenes, siguen limitados por su incapacidad para interactuar con el mundo exterior. Las herramientas cierran esta brecha, permitiendo a los agentes interactuar con datos y servicios externos y al mismo tiempo desbloquear una gama más amplia de acciones más allá de las del modelo subyacente por sí solo.
(fuente: documento técnico de agentes de Google)
Utilizando agentes y herramientas, podremos, desde nuestra interfaz de chat:
- recuperar datos de nuestros propios documentos
- leer/enviar correos electrónicos
- interactuar con bases de datos internas
- realizar búsquedas en Google en tiempo real
- etc.
2. ¿Qué son Agentes, Herramientas y Cadenas?
Un agente es una aplicación que intenta alcanzar un objetivo (o una tarea) teniendo a su disposición un conjunto de herramientas y tomando decisiones basadas en sus observaciones del entorno.
Un buen ejemplo de agente podría ser usted, por ejemplo: si necesita calcular una operación matemática compleja (objetivo), podría utilizar una calculadora (herramienta n.° 1) o un lenguaje de programación (herramienta n.° 2). Tal vez elegirías la calculadora para hacer una suma simple, pero elegirías la herramienta n.° 2 para algoritmos más complejos.
Por tanto, los agentes están formados por:
- Un modelo: el cerebro de nuestro agente es el LLM. Comprenderá la consulta (el objetivo) y navegará entre las herramientas disponibles para seleccionar la mejor.
- Uno o más herramientas : Estas son funciones, o API, que son responsables de realizar una acción específica (es decir, recuperar el tipo de cambio actual entre USD y EUR, agregar números, etc.)
- Un proceso de orquestación: así es como se comportará el modelo cuando se le pida que resuelva una tarea. Es un proceso cognitivo que define cómo el modelo analizará el problema, refinará las entradas, elegirá una herramienta, etc. Ejemplos de tales procesos son ReAct, CoT (Cadena de Pensamiento), ToT (Árbol de Pensamiento)
A continuación se muestra una explicación del flujo de trabajo.
Cadenas son de alguna manera diferentes. Mientras que los agentes pueden “decidir” por sí mismos qué hacer y qué pasos dar, las cadenas son sólo una secuencia de pasos predefinidos. Sin embargo, aún pueden confiar en las herramientas, lo que significa que pueden incluir un paso en el que deben seleccionar entre las herramientas disponibles. Cubriremos eso más tarde.
3. Crear un chat sencillo sin herramientas
Para ilustrar nuestro punto, primero que nada veremos cómo funciona nuestro LLM tal como está, sin ninguna ayuda.
Instalemos las bibliotecas necesarias:
vertexai==1.65.0
langchain==0.2.16
langchain-community==0.2.16
langchain-core==0.2.38
langchain-google-community==1.0.8
langchain-google-vertexai==1.0.6
Y cree nuestro chat muy simple usando Gemini LLM de Google:
from vertexai.generative_models import (
GenerativeModel,
GenerationConfig,
Part
)gemini_model = GenerativeModel(
"gemini-1.5-flash",
generation_config=GenerationConfig(temperature=0),
)
chat = gemini_model.start_chat()
Si ejecuta este sencillo chat y hace una pregunta sobre el tipo de cambio actual, probablemente obtenga una respuesta similar:
response = chat.send_message("What is the current exchange rate for USD vs EUR ?")
answer = response.candidates(0).content.parts(0).text--- OUTPUT ---
"I am sorry, I cannot fulfill this request. I do not have access to real-time information, including financial data like exchange rates."
No es sorprendente, como sabemos, los LLM no tienen acceso a datos en tiempo real.
Agreguemos una herramienta para eso. Nuestra herramienta será una pequeña función que llamará a una API para recuperar datos del tipo de cambio en tiempo real.
def get_exchange_rate_from_api(params):
url = f"https://api.frankfurter.app/latest?from={params('currency_from')}&to={params('currency_to')}"
print(url)
api_response = requests.get(url)
return api_response.text# Try it out !
get_exchange_rate_from_api({'currency_from': 'USD', 'currency_to': 'EUR'})
---
'{"amount":1.0,"base":"USD","date":"2024-11-20","rates":{"EUR":0.94679}}'
Ahora que sabemos cómo funcionan nuestras herramientas, nos gustaría decirle a nuestro LLM de chat que use esta función para responder nuestra pregunta. Por tanto, crearemos un agente monoherramienta. Para ello, tenemos varias opciones que enumeraré aquí:
- Utilice la API de chat Gemini de Google con llamadas a funciones
- Utilice la API de LangChain con agentes y herramientas
Ambos tienen sus ventajas y desventajas. El propósito de este artículo también es mostrarte las posibilidades y permitirte decidir cuál prefieres.
4. Agregar herramientas a nuestro chat: a la manera de Google con Function Calling
Básicamente, existen dos formas de crear una herramienta a partir de una función.
El primero es un enfoque de “diccionario” en el que usted especifica entradas y una descripción de la función en la herramienta. Los parámetros importantes son:
- Nombre de la función (sea explícito)
- Descripción: sea detallado aquí, ya que una descripción sólida y exhaustiva ayudará al LLM a seleccionar la herramienta adecuada.
- Parámetros: aquí es donde especifica sus argumentos (tipo y descripción). Nuevamente, sea detallado en la descripción de sus argumentos para ayudar al LLM a saber cómo pasar valor a su función.
import requestsfrom vertexai.generative_models import FunctionDeclaration
get_exchange_rate_func = FunctionDeclaration(
name="get_exchange_rate",
description="Get the exchange rate for currencies between countries",
parameters={
"type": "object",
"properties": {
"currency_from": {
"type": "string",
"description": "The currency to convert from in ISO 4217 format"
},
"currency_to": {
"type": "string",
"description": "The currency to convert to in ISO 4217 format"
}
},
"required": (
"currency_from",
"currency_to",
)
},
)
La segunda forma de agregar una herramienta usando el SDK de Google es con un from_func
creación de instancias. Esto requiere editar nuestra función original para que sea más explícita, con una cadena de documentación, etc. En lugar de ser detallados en la creación de la herramienta, estamos siendo detallados en la creación de la función.
# Edit our function
def get_exchange_rate_from_api(currency_from: str, currency_to: str):
"""
Get the exchange rate for currencies Args:
currency_from (str): The currency to convert from in ISO 4217 format
currency_to (str): The currency to convert to in ISO 4217 format
"""
url = f"https://api.frankfurter.app/latest?from={currency_from}&to={currency_to}"
api_response = requests.get(url)
return api_response.text
# Create the tool
get_exchange_rate_func = FunctionDeclaration.from_func(
get_exchange_rate_from_api
)
El siguiente paso consiste realmente en crear la herramienta. Para eso, agregaremos nuestra Declaración de Función a una lista para crear nuestro objeto Herramienta:
from vertexai.generative_models import Tool as VertexTooltool = VertexTool(
function_declarations=(
get_exchange_rate_func,
# add more functions here !
)
)
¡Pasemos eso ahora a nuestro chat y veamos si ahora puede responder nuestra consulta sobre los tipos de cambio! Recuerda, sin herramientas, nuestro chat respondió:
¡Probemos la herramienta de llamada de funciones de Google y veamos si esto ayuda! Primero, enviemos nuestra consulta al chat:
from vertexai.generative_models import GenerativeModelgemini_model = GenerativeModel(
"gemini-1.5-flash",
generation_config=GenerationConfig(temperature=0),
tools=(tool) #We add the tool here !
)
chat = gemini_model.start_chat()
response = chat.send_message(prompt)
# Extract the function call response
response.candidates(0).content.parts(0).function_call
--- OUTPUT ---
"""
name: "get_exchange_rate"
args {
fields {
key: "currency_to"
value {
string_value: "EUR"
}
}
fields {
key: "currency_from"
value {
string_value: "USD"
}
}
fields {
key: "currency_date"
value {
string_value: "latest"
}
}
}"""
El LLM adivinó correctamente que necesitaba utilizar el get_exchange_rate
función, y también adivinó correctamente los 2 parámetros eran USD
y EUR
.
Pero esto no es suficiente. ¡Lo que queremos ahora es ejecutar esta función para obtener nuestros resultados!
# mapping dictionnary to map function names and function
function_handler = {
"get_exchange_rate": get_exchange_rate_from_api,
}# Extract the function call name
function_name = function_call.name
print("#### Predicted function name")
print(function_name, "\n")
# Extract the function call parameters
params = {key: value for key, value in function_call.args.items()}
print("#### Predicted function parameters")
print(params, "\n")
function_api_response = function_handler(function_name)(params)
print("#### API response")
print(function_api_response)
response = chat.send_message(
Part.from_function_response(
name=function_name,
response={"content": function_api_response},
),
)
print("\n#### Final Answer")
print(response.candidates(0).content.parts(0).text)
--- OUTPUT ---
"""
#### Predicted function name
get_exchange_rate
#### Predicted function parameters
{'currency_from': 'USD', 'currency_date': 'latest', 'currency_to': 'EUR'}
#### API response
{"amount":1.0,"base":"USD","date":"2024-11-20","rates":{"EUR":0.94679}}
#### Final Answer
The current exchange rate for USD vs EUR is 0.94679. This means that 1 USD is equal to 0.94679 EUR.
"""
¡Ahora podemos ver que nuestro chat puede responder nuestra pregunta! Él:
- Adivinó correctamente la función para llamar,
get_exchange_rate
- Asignados correctamente los parámetros para llamar a la función.
{‘currency_from’: ‘USD’, ‘currency_to’: ‘EUR’}
- Obtuve resultados de la API
- ¡Y la respuesta está muy bien formateada para que sea legible por humanos!
Veamos ahora otra forma de hacerlo con LangChain.
5. Agregar herramientas a nuestro chat: al estilo Langchain con agentes
LangChain es un marco componible para construir con LLM. Es el marco de orquestación para flujos de trabajo agentes controlables.
De manera similar a lo que hicimos antes del estilo “Google”, crearemos herramientas al estilo Langchain. Comencemos por definir nuestras funciones. Al igual que con Google, debemos ser exhaustivos y detallados en las cadenas de documentación:
from langchain_core.tools import tool@tool
def get_exchange_rate_from_api(currency_from: str, currency_to: str) -> str:
"""
Return the exchange rate between currencies
Args:
currency_from: str
currency_to: str
"""
url = f"https://api.frankfurter.app/latest?from={currency_from}&to={currency_to}"
api_response = requests.get(url)
return api_response.text
Para darle vida a las cosas, agregaré otra herramienta que puede enumerar tablas en un conjunto de datos de BigQuery. Aquí está el código:
@tool
def list_tables(project: str, dataset_id: str) -> list:
"""
Return a list of Bigquery tables
Args:
project: GCP project id
dataset_id: ID of the dataset
"""
client = bigquery.Client(project=project)
try:
response = client.list_tables(dataset_id)
return (table.table_id for table in response)
except Exception as e:
return f"The dataset {params('dataset_id')} is not found in the {params('project')} project, please specify the dataset and project"
Una vez hecho esto, agregamos nuestras funciones a nuestra caja de herramientas LangChain.
langchain_tool = (
list_tables,
get_exchange_rate_from_api
)
Para construir nuestro agente, usaremos el AgentExecutor
objeto de LangChain. Este objeto básicamente tomará 3 componentes, que son los que definimos anteriormente:
Primero elijamos nuestro LLM:
gemini_llm = ChatVertexAI(model="gemini-1.5-flash")
Luego creamos un mensaje para gestionar la conversación:
prompt = ChatPromptTemplate.from_messages(
(
("system", "You are a helpful assistant"),
("human", "{input}"),
# Placeholders fill up a **list** of messages
("placeholder", "{agent_scratchpad}"),
)
)
Y finalmente creamos el AgentExecutor
y ejecutar una consulta:
agent = create_tool_calling_agent(gemini_llm, langchain_tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=langchain_tools)
agent_executor.invoke({
"input": "Which tables are available in the thelook_ecommerce dataset ?"
})--- OUTPUT ---
"""
{'input': 'Which tables are available in the thelook_ecommerce dataset ?',
'output': 'The dataset `thelook_ecommerce` is not found in the `gcp-project-id` project.
Please specify the correct dataset and project. \n'}
"""
Mmm. Parece que al agente le falta un argumento, o al menos pide más información… Respondamos dando esta información:
agent_executor.invoke({"input": f"Project id is bigquery-public-data"})--- OUPTUT ---
"""
{'input': 'Project id is bigquery-public-data',
'output': 'OK. What else can I do for you? \n'}
"""
Bueno, parece que volvemos al punto de partida. Al LLM se le dijo la identificación del proyecto, pero se olvidó de la pregunta. A nuestro agente parece faltarle memoria para recordar preguntas y respuestas anteriores. Quizás deberíamos pensar en…
6. Agregar memoria a nuestro agente
La memoria es otro concepto en Agentes, que básicamente ayuda al sistema a recordar el historial de conversaciones y evitar bucles interminables como el anterior. Piense en la memoria como un bloc de notas donde el LLM realiza un seguimiento de las preguntas y respuestas anteriores para crear contexto en torno a la conversación.
Modificaremos nuestro mensaje (instrucciones) al modelo para incluir memoria:
from langchain_core.chat_history import InMemoryChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory# Different types of memory can be found in Langchain
memory = InMemoryChatMessageHistory(session_id="foo")
prompt = ChatPromptTemplate.from_messages(
(
("system", "You are a helpful assistant."),
# First put the history
("placeholder", "{chat_history}"),
# Then the new input
("human", "{input}"),
# Finally the scratchpad
("placeholder", "{agent_scratchpad}"),
)
)
# Remains unchanged
agent = create_tool_calling_agent(gemini_llm, langchain_tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=langchain_tools)
# We add the memory part and the chat history
agent_with_chat_history = RunnableWithMessageHistory(
agent_executor,
lambda session_id: memory, #<-- NEW
input_messages_key="input",
history_messages_key="chat_history", #<-- NEW
)
config = {"configurable": {"session_id": "foo"}}
Ahora volveremos a ejecutar nuestra consulta desde el principio:
agent_with_chat_history.invoke({
"input": "Which tables are available in the thelook_ecommerce dataset ?"
},
config
)--- OUTPUT ---
"""
{'input': 'Which tables are available in the thelook_ecommerce dataset ?',
'chat_history': (),
'output': 'The dataset `thelook_ecommerce` is not found in the `gcp-project-id` project. Please specify the correct dataset and project. \n'}
"""
Con un historial de chat vacío, el modelo aún solicita la identificación del proyecto. Bastante consistente con lo que teníamos antes con un agente sin memoria. Respondamos al agente y agreguemos la información que falta:
reply = "Project id is bigquery-public-data"
agent_with_chat_history.invoke({"input": reply}, config)--- OUTPUT ---
"""
{'input': 'Project id is bigquery-public-data',
'chat_history': (HumanMessage(content='Which tables are available in the thelook_ecommerce dataset ?'),
AIMessage(content='The dataset `thelook_ecommerce` is not found in the `gcp-project-id` project. Please specify the correct dataset and project. \n')),
'output': 'The following tables are available in the `thelook_ecommerce` dataset:\n- distribution_centers\n- events\n- inventory_items\n- order_items\n- orders\n- products\n- users \n'}
"""
Observe cómo, en la salida:
- El “historial de chat” realiza un seguimiento de las preguntas y respuestas anteriores
- ¡La salida ahora devuelve la lista de las tablas!
'output': 'The following tables are available in the `thelook_ecommerce` dataset:\n- distribution_centers\n- events\n- inventory_items\n- order_items\n- orders\n- products\n- users \n'}
Sin embargo, en algunos casos de uso, ciertas acciones pueden requerir atención especial debido a su naturaleza (es decir, eliminar una entrada en una base de datos, editar información, enviar un correo electrónico, etc.). La automatización total sin control puede llevar a situaciones en las que el agente tome decisiones equivocadas y genere daños.
Una forma de proteger nuestros flujos de trabajo es agregar un paso humano involucrado.
7. Creando una Cadena con un paso de Validación Humana
Una cadena es algo diferente de un agente. Mientras que el agente puede decidir si utilizar o no herramientas, una cadena es más estática. Es una secuencia de pasos, para la cual aún podemos incluir un paso donde el LLM elegirá entre un conjunto de herramientas.
Para construir cadenas en LangChain, utilizamos LCEL.
LangChain Expression Language, o LCEL, es una forma declarativa de componer cadenas fácilmente. Las cadenas en LangChain usan el operador de canalización `|` para indicar las órdenes en las que se deben ejecutar los pasos, como step 1 | step 2 | step 3 etc.
La diferencia con los Agentes es que las Cadenas siempre seguirán esos pasos, mientras que los Agentes pueden “decidir” por sí mismos y son autónomos en su proceso de toma de decisiones.
En nuestro caso, procederemos de la siguiente manera para construir un simple prompt | llm
cadena.
# define the prompt with memory
prompt = ChatPromptTemplate.from_messages(
(
("system", "You are a helpful assistant."),
# First put the history
("placeholder", "{chat_history}"),
# Then the new input
("human", "{input}"),
# Finally the scratchpad
("placeholder", "{agent_scratchpad}"),
)
)# bind the tools to the LLM
gemini_with_tools = gemini_llm.bind_tools(langchain_tool)
# build the chain
chain = prompt | gemini_with_tools
¿Recuerdas cómo en el paso anterior pasamos un agente a nuestro `RunnableWithMessageHistory`? Bueno, aquí haremos lo mismo, pero…
# With AgentExecutor# agent = create_tool_calling_agent(gemini_llm, langchain_tool, prompt)
# agent_executor = AgentExecutor(agent=agent, tools=langchain_tool)
# agent_with_chat_history = RunnableWithMessageHistory(
# agent_executor,
# lambda session_id: memory,
# input_messages_key="input",
# history_messages_key="chat_history",
# )
config = {"configurable": {"session_id": "foo"}}
# With Chains
memory = InMemoryChatMessageHistory(session_id="foo")
chain_with_history = RunnableWithMessageHistory(
chain,
lambda session_id: memory,
input_messages_key="input",
history_messages_key="chat_history",
)
response = chain_with_history.invoke(
{"input": "What is the current CHF EUR exchange rate ?"}, config)
--- OUTPUT
"""
content='',
additional_kwargs={
'function_call': {
'name': 'get_exchange_rate_from_api',
'arguments': '{"currency_from": "CHF", "currency_to": "EUR"}'
}
}
"""
A diferencia del agente, una cadena no proporciona la respuesta a menos que se lo indiquemos. En nuestro caso, se detuvo en el paso donde LLM devuelve la función que debe llamarse.
Necesitamos agregar un paso adicional para realmente llamar la herramienta. Agreguemos otra función para llamar a las herramientas:
from langchain_core.messages import AIMessagedef call_tools(msg: AIMessage) -> list(dict):
"""Simple sequential tool calling helper."""
tool_map = {tool.name: tool for tool in langchain_tool}
tool_calls = msg.tool_calls.copy()
for tool_call in tool_calls:
tool_call("output") = tool_map(tool_call("name")).invoke(tool_call("args"))
return tool_calls
chain = prompt | gemini_with_tools | call_tools #<-- Extra step
chain_with_history = RunnableWithMessageHistory(
chain,
lambda session_id: memory,
input_messages_key="input",
history_messages_key="chat_history",
)
# Rerun the chain
chain_with_history.invoke({"input": "What is the current CHF EUR exchange rate ?"}, config)
Ahora obtenemos el siguiente resultado, que muestra que la API se ha llamado correctamente:
({'name': 'get_exchange_rate_from_api',
'args': {'currency_from': 'CHF', 'currency_to': 'EUR'},
'id': '81bc85ea-dfd4-4c01-85e8-f3ca592fff5b',
'type': 'tool_call',
'output': '{"amount":1.0,"base":"USD","date":"2024-11-20","rates":{"EUR":0.94679}}'
})
Ahora que hemos entendido cómo encadenar pasos, ¡agreguemos nuestro paso humano en el circuito! Queremos que este paso verifique que el LLM haya entendido nuestras solicitudes y realizará la llamada correcta a una API. Si el LLM ha entendido mal la solicitud o utilizará la función incorrectamente, podemos decidir interrumpir el proceso.
def human_approval(msg: AIMessage) -> AIMessage:
"""Responsible for passing through its input or raising an exception.Args:
msg: output from the chat model
Returns:
msg: original output from the msg
"""
for tool_call in msg.tool_calls:
print(f"I want to use function ({tool_call.get('name')}) with the following parameters :")
for k,v in tool_call.get('args').items():
print(" {} = {}".format(k, v))
print("")
input_msg = (
f"Do you approve (Y|y)?\n\n"
">>>"
)
resp = input(input_msg)
if resp.lower() not in ("yes", "y"):
raise NotApproved(f"Tool invocations not approved:\n\n{tool_strs}")
return msg
A continuación, agregue este paso a la cadena antes de la llamada a la función:
chain = prompt | gemini_with_tools | human_approval | call_toolsmemory = InMemoryChatMessageHistory(session_id="foo")
chain_with_history = RunnableWithMessageHistory(
chain,
lambda session_id: memory,
input_messages_key="input",
history_messages_key="chat_history",
)
chain_with_history.invoke({"input": "What is the current CHF EUR exchange rate ?"}, config)
Luego se le pedirá que confirme que el LLM entendió correctamente:
Este paso del ser humano puede ser muy útil para flujos de trabajo críticos donde una mala interpretación del LLM podría tener consecuencias dramáticas.
8. Usar herramientas de búsqueda
Una de las herramientas más convenientes para recuperar información en tiempo real son los motores de búsqueda. Una forma de hacerlo es utilizar GoogleSerperAPIWrapper
(deberá registrarse para obtener una clave API para poder usarlo), que proporciona una interfaz agradable para consultar la Búsqueda de Google y obtener resultados rápidamente.
Afortunadamente, LangChain ya le proporciona una herramienta, por lo que no tendremos que escribir la función nosotros mismos.
Por lo tanto, intentemos hacer una pregunta sobre el evento de ayer (20 de noviembre) y ver si nuestro agente puede responder. Nuestra pregunta es sobre el último partido oficial de Rafael Nadal (que perdió ante van de Zandschulp).
agent_with_chat_history.invoke(
{"input": "What was the result of Rafael Nadal's latest game ?"}, config)--- OUTPUT ---
"""
{'input': "What was the result of Rafael Nadal's latest game ?",
'chat_history': (),
'output': "I do not have access to real-time information, including sports results. To get the latest information on Rafael Nadal's game, I recommend checking a reliable sports website or news source. \n"}
"""
Sin poder acceder a la Búsqueda de Google, nuestro modelo no puede responder porque esta información no estaba disponible en el momento en que fue entrenado.
Ahora agreguemos nuestra herramienta Serper a nuestra caja de herramientas y veamos si nuestro modelo puede usar la Búsqueda de Google para encontrar la información:
from langchain_community.utilities import GoogleSerperAPIWrapper# Create our new search tool here
search = GoogleSerperAPIWrapper(serper_api_key="...")
@tool
def google_search(query: str):
"""
Perform a search on Google
Args:
query: the information to be retrieved with google search
"""
return search.run(query)
# Add it to our existing tools
langchain_tool = (
list_datasets,
list_tables,
get_exchange_rate_from_api,
google_search
)
# Create agent
agent = create_tool_calling_agent(gemini_llm, langchain_tool, prompt)
agent_executor = AgentExecutor(agent=agent, tools=langchain_tool)
# Add memory
memory = InMemoryChatMessageHistory()
agent_with_chat_history = RunnableWithMessageHistory(
agent_executor,
lambda session_id: memory,
input_messages_key="input",
history_messages_key="chat_history",
)
Y vuelva a ejecutar nuestra consulta:
agent_with_chat_history.invoke({"input": "What was the result of Rafael Nadal's latest game ?"}, config)--- OUTPUT ---
"""
{'input': "What was the result of Rafael Nadal's latest game ?",
'chat_history': (),
'output': "Rafael Nadal's last match was a loss to Botic van de Zandschulp in the Davis Cup. Spain was eliminated by the Netherlands. \n"}
"""
Conclusión
Los LLM por sí solos a menudo se topan con un obstáculo cuando se trata de utilizar datos personales, corporativos, privados o reales. De hecho, dicha información generalmente no está disponible durante el período de capacitación. Los agentes y las herramientas son una forma poderosa de aumentar estos modelos al permitirles interactuar con sistemas y API, y organizar flujos de trabajo para aumentar la productividad.