Desarrollo Web Inteligencia Artificial Programación

Agregándole una herramienta al cinturón de Batman

Configuraremos una tool que obtiene los mensajes históricos de la interacción entre el usuario y la IA para que esta pueda utilizarlos en sus futuras respuestas. Añadiéndole una funcionalidad personalizada al LLM integrado

Adrian Vega Adrian Vega
· · 17 min lectura · 32 vistas

En la entrada del blog anterior, te mostré como implementar un Chat Box con inteligencia artificial utilizando la Api de Anthropic (si no lo viste aun, te dejo el enlace: Integrado IA por primera vez dentro de un sistema en Next.js - Adrian Vega T.). Y espero que al igual que como me paso a mí en su momento, te preguntases al final… Pero ¿cómo lo personalizo para que utilizarlo específicamente para tareas de mi sistema?


Y acá es donde entra el término "Tool use", que es la conexión que tienen los modelos de inteligencia artificial para acceder a información con la cual no han sido entrenadas, como lo podría ser, información de tu base de datos, búsquedas web, comunicación vía email o SMS, lectura o creación de archivos, entre muchas otras tareas.


Esto nos da la posibilidad de aprovechar la capacidad de análisis de los LLMs para añadir tareas específicas a nuestros sistemas o potenciar las que ya realizan, pasando la barrera de la interacción con la IA únicamente a través de texto, dándole herramientas para extender sus capacidades y su rango de acción.   


¿Por qué son necesarias las tools para extender las capacidades de los LLMs?

Los Modelos de Lenguaje (LLMs) fueron entrenados con miles de datos, de esa manera es como han aprendido a asociar, a razonar, a identificar patrones, obtener conclusiones, etc. Pero todo este entrenamiento fue básicamente a través de texto y tiene una fecha límite en la cual obtuvo esa información, por lo que no puede acceder por sí mismo a información más reciente. ¿Pero entonces como hace para mostrarnos resultados correctos cuando le preguntamos por algún hecho reciente? Obtiene la información de tools de búsqueda web, para luego procesar, razonar y sacar conclusiones según su entrenamiento.


De esa misma manera nosotros podemos añadir tools al LLM que estemos usando en nuestro sistema para darle acceso a cierta información de nuestra base de datos para que la procese y razone sobre ella. Te explico de manera breve cual es flujo del sistema ya con una tool integrada para que tengas la secuencia clara antes de pasar al código.


  1. El usuario hace una petición
  2. El LLM la procesa y decide si puede responder por sí mismo devuelve la respuesta, pero si necesita utilizar una tool revisa que tools tiene disponibles y se guía por su descripción para saber si es funcional o no para ese caso específico.
  3. Si encuentra una tool funcional verifica los requerimientos de uso y los prepara para pasárselos a la función ligada a la tool y espera el resultado.
  4. Mientras el LLM espera el resultado, la función se procesa y devuelve los datos que le fueron solicitados.
  5. Pasamos todo el contexto de la conversación más el resultado obtenido de la tool para que el LLM formule una respuesta lógica y coherente para brindársela al usuario.
  6. El LLM responde al usuario.


Explicado esto, te mostrare como puedes agregar una tool a tu sistema con una LLM.


Notas antes de iniciar:

  • Vamos a realizar el ejemplo en Python y utilizaremos Google Colab (https://colab.research.google.com/) para evitar instalaciones o problemas de entorno.
  • La función getMessage que usare será genérica con una colección de datos simulando una tabla de mensajes obtenida desde una base de datos, en un entorno real esa función debería de obtener el objeto desde una consulta a una base de datos.
  • Debes tener acceso a una Api Key en tu cuenta de Anthropic, esta es distinta a tu plan de claude.ai si es que tienes algún plan, puedes recargar desde $5 para usos experimentales como el que desarrollaremos en este post. Puedes acceder a más información en https://platform.claude.com/


Preparando el entorno


Ingresa Google Colab en el siguiente enlace https://colab.research.google.com/ y luego da clic en "Nuevo cuaderno", si no ves la opción puedes ir al menú superior en "Archivo" selecciona "Cuaderno nuevo en drive".


Colocas el nombre de tu preferencia, por ejemplo "Tools con Python". Y aparecerá el cuaderno y la celda en la que vamos a ir escribiendo el código.


Decidí mostrarte el proceso en Google Colab para poder tener todo en una misma celda y ahorrarnos los pasos del front-end, así que acá abordaremos específicamente la lógica de implementación de la tool.


Ahora preparemos la única variable de entorno que necesitaremos, que será la api key de Anthropic, esta nunca debe ponerse directamente en la celda, ya que si el cuaderno es publico las personas que ingresen a ese cuaderno podrán ver la llave publicada.


Para evitar eso, vamos a ingresar en la opción "Secretos" que está en la parte izquierda de la pantalla y a la fecha se simboliza con el icono de una llave.


Allí damos clic a "Añadir secreto nuevo", le colocamos de nombre ANTHROPIC_API_KEY, y en la sección de "Valor" le pegamos la Api Key (ver notas antes de iniciar) y habilitamos el "Acceso desde el cuaderno". Esto es el equivalente a que coloquemos la api key en nuestro archivo .env


Pasamos al cuaderno y nos ubicamos en la celda para empezar a colocar el código… todo lo haremos dentro de la misma celda.


Para iniciar vamos a hacer las importaciones de las librerías necesarias para tener acceso a la api de Anthropic, a la key que guardamos en "secretos" y la librería datetime que utilizaremos para formatear las fechas.


#Libreria de Anthropic
import anthropic

#Libreria de acceso a la key en "secretos"
from google.colab import userdata

#Libreria para formato de fechas
from datetime import datetime, timedelta


Ahora instanciamos el objeto Anthropic y los configuramos con la llave que guardamos en secretos para establecer una conexión exitosa con la api de Anthropic.


client = anthropic.Anthropic(
   api_key = userdata.get("ANTHROPIC_API_KEY")
)


Así obtendremos acceso a las funcionalidades la api a través de la variable "client" para el proceso de interacción con el modelo de IA.


Y ahora vamos a crear la tool, con los diferentes componentes que debe de tener para que el LLM lo reconozca, sepa que hace y que variables necesita.


tools = [
   {
               #Nombre de la tool
       "name" : "getMessages",
               #Descripcion detallada de que hace, cuando lo hace y como devuelve el resultado
       "description" : """Through this tool you will get access to messages's table, especifically to the user messages who is active in the session, you will use this tool when the user ask about any information about his messages, for example: how many messages he sends in a period, what is his more recurrent topic, a summary about his messages, or something about message introspection or about specific data, the function will return its messages in an object to you, and you are authorized to process that information to formulate a complete answer""",
       "input_schema": {
           "type" : "object",
               #Que variables necesita esta tool para cumplir su función
           "properties":{
               "period" : {
                 "type": "string",
                 "description" : "Period of time to delimitate messages to get, it could be: day, week, month, year or all",
                 "enum": ["day", "week", "month", "year", "all"]
               },
               "keyword": {
                   "type" : "string",
                   "description" : "You have to search for keywords into user's messages in order to get relevant information"
               }
           },
               #Que variables son obligatorias
           "required": ["period"]
       }
   }
]


De esta manera debemos estructurar el objeto para que el LLM sepa exactamente que necesita la tool para funcionar, el punto más importante es colocar una buena descripción ya que es por lo que el LLM se guía para saber que tool debe usar, al LLM no le importa el nombre o los parámetros para decidir si puede usar una tool o no, se guía específicamente por este campo. Una buena descripción debe tener que hace la tool, cuando debe hacerlo (es decir, sobre qué dato pregunta el usuario), y como entrega esos datos, para que el LLM sepa específicamente como utilizarla.


Esta tool está ligada a una función, que es la que procesa la petición del LLM y devuelve el resultado, esta función debe cumplir con lo descrito en la tool, debe usar los parámetros solicitados y debe devolver la información de manera antes descrita en el objeto (tool). En este caso usaremos una función que simula una conexión a la base de datos y obtiene los mensajes anteriores entre el usuario y la IA (No haremos la conexión a la base para simplificar el proceso).


#definimos la función con los parámetros descritos en la tool
def get_messages(period, keyword=""):
   #Conectarme a supabase
   #supabase = "supabase conection"

   #Obtener mensajes
   #messages = supabase.from('messages').select('response').eq('user_id',supabase.user.id).orderBy('created_at',desc)
 
 #Simulamos el contenido de la tabla de mensajes
   all_messages = [
       {"response": "Hablamos sobre tool use en TypeScript", "created_at": datetime.now() - timedelta(days=1)},
       {"response": "Revisamos los conceptos de RAG", "created_at": datetime.now() - timedelta(days=3)},
       {"response": "Configuramos el SDK de Anthropic", "created_at": datetime.now() - timedelta(days=8)},
       {"response": "Discutimos Python vs TypeScript", "created_at": datetime.now() - timedelta(days=15)},
       {"response": "Exploramos embeddings y búsqueda semántica", "created_at": datetime.now() - timedelta(days=40)}
   ]

#filtramos los mensajes obtenido por el parámetro "period"
   now = datetime.now()
 
   #Filtrar por periodo
   if period == "day":
       start = now - timedelta(days=1)
   elif period == "week":
       start = now - timedelta(days=7)
   elif period == "month":
       start = now - timedelta(days=30)
   elif period == "year":
       start = now - timedelta(days=365)
   else:
       start = None
 
   if start:
       messages = [m for m in all_messages if m["created_at"] >= start]
   else:
       messages = all_messages
 
   #filtrar por keword si existe
   if keyword != "":
       messages = [m for m in messages if keyword.lower() in m["response"].lower()]
 
   #retornar consulta
   return {
       "count": len(messages),
       "messages": [m["response"] for m in messages]
   }


Esta funcionalidad le devolverá al LLM los resultados según la petición de usuario, por ejemplo: Si el usuario pregunta, ¿Cuántos mensajes envié la última semana? El LLM pasara como parámetro "period' el string "week", para que la función le devuelva específicamente los resultados de la última semana y con eso formular la respuesta para el usuario.


Ahora solo nos queda programar la función que interactúa con el modelo IA, así que pasemos a ello:


#Definimos la función y le pasamos como parámetro la pregunta del usuario
def call_agent(question):


En este punto se produce la primera interacción con la IA, que es cuando el usuario pregunta algo y IA analiza y si puede responder por sí misma pasara hacia el return directamente


   #Resolver pregunta del usuario
   agent = client.messages.create(
       model = "claude-haiku-4-5-20251001",
       max_tokens = 1024,
       tools = tools,
       messages = [{"role":"user", "content":f"{question}"}]
   )


Pero si no puede resolver la petición del usuario, lanzara un "stop_reason", Claude tiene varios stop_reasons, entre las cuales están:

  • end_turn, que es cuando se devuelve una respuesta "exitosa", es decir, cuando el LLM resolvió por sí mismo.
  • max_tokens, cuando se ha excedido el límite de tokens delimitado en la sección anterior.
  • tool_use que es que nos interesa en este caso, cuando el LLM indica que debe usar uno de los tools declarados.
  • refusal, se activa cuando se está preguntando algo que está fuera de los límites de seguridad.


Entonces, cuando lanza un stop_reason del tipo tool_use ingresa a esta parte del código y utiliza la función vinculada a la tool


   #Verificar si es necesario el uso de tools
   if agent.stop_reason == 'tool_use':
       #verificar el nombre de tool use que Claude necesita usar y sus parámetros
       tool_block = next(block for block in agent.content if block.type == "tool_use")
       tool_name = tool_block.name
       tool_input = tool_block.input
 
       #Identificar y configurar la función específica que se debe usar
       if tool_name == "getMessages":
           tool_result = get_messages(
               period=tool_input["period"],
               keyword=tool_input.get("keyword", "")
           )


Una vez procesada la petición, volvemos a hacer otra interacción con el LLM ahora para devolverle todos los mensajes, más la información obtenida a través de la función get_messages, es necesario pasarle todo nuevamente porque el LLM no tiene memoria por sí mismo, y si no le pasamos los mensajes anteriores no tendrá el contexto suficiente para dar una respuesta coherente.


       #Obtener la respuesta del modelo desde el uso de la tool
       final_response = client.messages.create(
           model = "claude-haiku-4-5-20251001",
           max_tokens = 1024,
           tools=tools,
           messages = [
               {"role": "user", "content": question},
               {"role": "assistant", "content": agent.content},
               {
                   "role": "user",
                   "content": [
                       {
                           "type": "tool_result",
                           "tool_use_id": tool_block.id,
                           "content": str(tool_result)
                       }
                   ]
               }
           ]
       )

       #retornar respuesta con el uso de la tool
       return final_response.content[0].text

   #Retornar respuesta en su flujo simple
   return agent.content[0].text


Una vez escrito todo el código anterior, podemos probar que tal funciona y puedes ir cambiando la pregunta para asegurarte que funcione correctamente y usa la tool de manera adecuada.


print(call_agent("¿Que tools tienes disponibles?"))


Con el uso de tools conseguimos personalización en el uso de un modelo IA aplicado a nuestro sistema, pasando de ser un modelo comercial a un modelo que razona sobre mis datos específicos, o más bien, sobre los datos a los que yo le brindo acceso a través de la funciones, aprovechando su capacidad de procesamiento e interacción a través de lenguaje natural.


Espero que esta información sea de ayuda para tu proceso y puedas implementarlo en tus propios proyectos, déjame en los comentarios en que áreas podrías sacarle mayor provecho a esta funcionalidad aplicada a tus sistemas.

Tags

#TypeScript #IA #Anthropic #Claude #Tools

Compartir

Comentarios (0)

Inicia sesión para dejar un comentario

Entrar con email

No hay comentarios aún

Sé el primero en comentar