Construcción de un asistente RAG agente con JavaScript, Mastra y Elasticsearch

Aprende a construir agentes de IA en el ecosistema JavaScript

Elasticsearch tiene integraciones nativas con las herramientas y proveedores líderes en la industria de IA generativa. Echa un vistazo a nuestros webinars sobre cómo ir más allá de los conceptos básicos de RAG o crear apps listas para la producción con la base de datos vectorial de Elastic.

Para crear las mejores soluciones de búsqueda para tu caso de uso, inicia una prueba gratuita en el cloud o prueba Elastic en tu máquina local ahora mismo.

Esta idea se me ocurrió en medio de una liga de baloncesto de fantasía muy intensa y de alto riesgo. Me preguntaba: ¿Podría crear un agente de IA que me ayudara a dominar mis enfrentamientos semanales? ¡Absolutamente!

En esta entrada, exploraremos cómo construir un asistente RAG agente usando Mastra y una aplicación sitio web ligero en JavaScript para interactuar con él. Al conectar este agente con Elasticsearch, le damos acceso a datos estructurados de jugadores y la capacidad de ejecutar agregaciones estadísticas en tiempo real, para ofrecerte recomendaciones basadas en estadísticas de jugadores. Visita el repositorio de GitHub para seguirle; el README proporciona instrucciones sobre cómo clonar y ejecutar la aplicación por tu cuenta.

Así debería ver cuando todo esté montado:

Nota: Esta entrada del blog se basa en "Construcción de agentes de IA con SDK de IA y Elastic". Si eres nuevo en los agentes de IA en general y en qué podrían servir, empieza por ahí.

Visión general de la arquitectura

En el núcleo del sistema se encuentra un gran modelo de lenguaje (LLM), que actúa como motor de razonamiento del agente (el cerebro). Interpreta la entrada del usuario, decide qué herramientas llamar y orquesta los pasos necesarios para generar una respuesta relevante.

El propio agente está estructurado por Mastra, un framework de agentes dentro del ecosistema JavaScript. Mastra envuelve el LLM con infraestructura backend, lo expone como un endpoint API y proporciona una interfaz para definir herramientas, indicaciones del sistema y comportamiento de agentes.

En el frontend, usamos Vite para andamiar rápidamente una aplicación sitio web React que proporciona una interfaz de chat para enviar consultas al agente y recibir sus respuestas.

Por último, tenemos Elasticsearch, que almacena estadísticas de jugadores y datos de emparejamientos que el agente puede consultar y agregar.

Fondo

Vamos a repasar algunos conceptos fundamentales:

¿Qué es el RAG agente?

Los agentes de IA pueden interactuar con otros sistemas, operar de forma independiente y realizar acciones basadas en sus parámetros definidos. El RAG agente combina la autonomía de un agente de IA con los principios de generación aumentada por recuperación, permitiendo a un LLM elegir qué herramientas llamar y qué datos usar como contexto para generar una respuesta. Lee más sobre RAG aquí.

Elegir un framework, ¿por qué ir más allá del SDK de IA?

Hay muchos frameworks de agentes de IA disponibles y probablemente oíste hablar de los más populares como CrewAI, AutoGen y LangGraph. La mayoría de estos frameworks comparten un conjunto común de funcionalidades, incluyendo soporte para diferentes modelos, uso de herramientas y gestión de memoria.

Aquí tienes una hoja comparativa de marcos de Harrison Chase (CEO de LangChain).

Lo que despertó mi interés con Mastra es que es un framework JavaScript-first diseñado para que desarrolladores full-stack integren fácilmente agentes en su ecosistema. El AI-SDK de Vercel también hace la mayoría de esto, pero donde Mastra destaca es cuando tus proyectos incluyen flujos de trabajo de agentes más complejos. Mastra mejora los patrones base establecido por el AI-SDK y en este proyecto los usaremos conjuntamente.

Marcos y consideraciones sobre la elección del modelo

Aunque estos frameworks pueden ayudarte a construir agentes de IA rápidamente, existen algunos inconvenientes a tener en cuenta. Por ejemplo, al usar cualquier otro framework fuera de agentes de IA o cualquier capa de abstracción en general, pierdes un poco de control. Si el LLM no emplea correctamente las herramientas o hace algo que no quieres, la abstracción dificulta la depuración. Aun así, en mi opinión, este equilibrio merece la facilidad y rapidez que obtienes al construir, especialmente porque estos frameworks están ganando impulso y se iteran constantemente.

De nuevo, estos frameworks son independientes de los modelos, lo que significa que puedes conectar y jugar diferentes modelos; recuerda que los modelos varían en los conjuntos de datos con los que fueron capacitados y, a su vez, varían en las respuestas que dan. Algunos modelos ni siquiera soportan la llamada de herramientas. Así que es posible cambiar y probar diferentes modelos para ver cuál te da las mejores respuestas, pero ten en cuenta que probablemente tendrás que reescribir el prompt del sistema para cada uno. Por ejemplo, usando Llama3.3 en comparación con GPT-4o, implica mucho más indicación e instrucciones específicas para obtener la respuesta que buscas.

Baloncesto de fantasía de la NBA

El baloncesto de fantasía consiste en empezar una liga con un grupo de colegas (advertencia, dependiendo de lo competitivo que sea tu grupo, esto podría afectar al estado de tus amistades), normalmente con algo de dinero en juego. Cada uno de vosotros selecciona un equipo de 10 jugadores para competir contra los 10 jugadores de otro amigo alternando semanalmente. Los puntos que contribuyen a tu puntaje global son cómo se desempeña cada uno de tus jugadores contra sus oponentes en una semana determinada.

Si un jugador de tu equipo se lesiona, es suspendido, etc., hay una lista de jugadores agentes libres disponibles para agregar a tu equipo. Aquí es donde ocurre gran parte de la dificultad en los deportes de fantasía, porque solo tienes un número limitado de fichas y todos están constantemente a la caza del mejor jugador.

Aquí es donde nuestro asistente de IA de la NBA brillará, especialmente en situaciones en las que tienes que decidir rápidamente qué jugador elegir. En lugar de tener que buscar manualmente cómo rinde un jugador contra un oponente específico, el asistente puede encontrar esos datos rápidamente y comparar promedios para darte una recomendación informada.

Ahora que ya sabes lo básico sobre el RAG agente y el baloncesto fantasy de la NBA, vamos a verlo en la práctica.

Construcción del proyecto

Si te quedas atascado en algún momento o no quieres montarlo desde cero, por favor consulta el repositorio.

Lo que vamos a cubrir

  1. Andamiaje del proyecto:
    1. Backend (Mastra): Usa NPX Create mastra@latest para andamiar el backend y definir la lógica del agente.
    2. Frontend (Vite + React): Usa npm create vite@latest para construir la interfaz de chat del frontend y así interactuar con el agente.
  2. Configuración de variables de entorno
    1. Instala dotenv para gestionar las variables del entorno.
    2. Crea un .env archiva y proporciona las variables requeridas.
  3. Configuración de Elasticsearch
    1. Crea un clúster de Elasticsearch (ya sea localmente o en la nube).
    2. Instala el cliente oficial de Elasticsearch.
    3. Cerciórate de que las variables del entorno sean accesibles.
    4. Establece conexión con el cliente.
  4. Ingiriendo en masa datos de la NBA en Elasticsearch
    1. Crea un índice con los mapeos apropiados para permitir agregaciones.
    2. Ingirir en masa las estadísticas de los jugadores de un archivo CSV en un índice de Elasticsearch.
  5. Definir agregaciones de Elasticsearch
    1. Consulta para calcular promedios históricos contra un oponente específico.
    2. Consulta para calcular los promedios de temporada contra un rival específico.
  6. Archivo utilitario de comparación de jugadores
    1. Consolida funciones auxiliares y agregaciones de Elasticsearch.
  7. Construcción del agente
    1. Agrega la definición del agente y el prompt del sistema.
    2. Instala Zod y define herramientas.
    3. Agregar una configuración de middleware para manejar CORS.
  8. Integración del frontend
    1. Usando el useChat de AI-SDK para interactuar con el agente.
    2. Crea la interfaz para mantener conversaciones bien formateadas.
  9. Ejecutando la aplicación
    1. Inicia tanto el backend (servidor Mestra) como el frontend (app React).
    2. Ejemplos de consultas y uso.
  10. Qué sigue: Hacer que el agente sea más inteligente
    1. Agregar capacidades de búsqueda semántica para permitir recomendaciones más profundas.
    2. Habilitar la consulta dinámica moviendo la lógica de búsqueda al servidor Elasticsearch MCP (Model Context Protocol).

Prerrequisitos

  • Node.js y NPM: Tanto el backend como el frontend funcionan en Node. Cerciórate de tener instalados Node 18+ y npm v9+ (que vienen incluidos con Node 18+).
  • Clúster de Elasticsearch: Un clúster activo de Elasticsearch, ya sea localmente o en la nube.
  • Clave API de OpenAI: Genera una en la página de claves API del portal para desarrolladores de OpenAI.

Estructura del proyecto

Paso 1: Estructurar el proyecto

  1. Primero, crea el directorio nba-ai-assistant-js y navega dentro usando:

Backend:

  1. Usa la herramienta de creación de Mastra con el comando:

2. Deberías recibir algunos prompts en tu terminal; para el primero, llamaremos al backend del proyecto:

3. A continuación, mantendremos la estructura predeterminada para almacenar los archivos Mastra, así que introduzca src/.

4. Luego, elegiremos OpenAI como nuestro proveedor de LLM por defecto.

5. Finalmente, te pedirá la clave de la API de OpenAI. Por ahora, elegiremos la opción de saltarlo y proporcionarlo más adelante en un archivo .env .

Frontend:

  1. Vuelve al directorio raíz y ejecuta la herramienta de creación de Vite usando este comando: npm create vite@latest frontend -- --template react

Esto debería crear una aplicación ligera de React llamada frontend con una plantilla específica para React.

Si todo va bien, dentro de tu directorio de proyecto, deberías estar mirando un directorio backend que contenga el código Mastra y un directorio frontend con tu app React.

Paso 2: Configuración de variables de entorno

  1. Para gestionar claves sensibles, usaremos el paquete dotenv para cargar nuestras variables de entorno desde el .env archivo. Navega al directorio del backend e instala dotenv:

2. Mientras está en el directorio backend, se proporciona un archivo example.env con las variables adecuadas para rellenar. Si creas el tuyo propio, cerciórate de incluir las siguientes variables:

Nota: Cerciórate de que este archivo esté excluido de tu control de versiones agregando .env a .gitignore.

Paso 3: Configuración de Elasticsearch

Primero, necesitas un clúster activo de Elasticsearch. Hay dos opciones:

  • Opción A: Usar Elasticsearch Cloud
    • Apúntate a Elastic Cloud
    • Crear un nuevo despliegue
    • Obtén la URL de tu endpoint y la clave API (codificada)
  • Opción B: Ejecutar Elasticsearch localmente
    • Instala y ejecuta Elasticsearch localmente
    • Usa http://localhost:9200 como punto final
    • Generar una clave API

Instalación del cliente Elasticsearch en el backend:

  1. Primero, instala el cliente oficial de Elasticsearch en tu directorio backend:

2. Luego crea una lib de directorios para almacenar funciones reutilizables y navega hacia ella:

3. Dentro, crea un nuevo archivo llamado elasticClient.js. Este archivo inicializará el cliente Elasticsearch y lo expondrá para su uso en todo tu proyecto.

4. Como usamos módulos ECMAScript (ESM), __dirname and __nombre de archivo no están disponibles. Para cerciorarte de que tus variables de entorno se carguen correctamente desde el archivo .env Archivo en la carpeta de backend, agrega esta configuración en la parte superior de tu archivo:

5. Ahora, inicializa el cliente Elasticsearch usando tus variables de entorno y comprueba la conexión:

Ahora, podemos importar esta instancia cliente a cualquier archivo que necesite interactuar con tu clúster de Elasticsearch.

Paso 4: Ingirir en masa datos de la NBA en Elasticsearch

Conjunto de datos:

Para este proyecto, consultaremos los conjuntos de datos disponibles en el directorio de backend/datos del repositorio. Nuestro asistente de la NBA empleará estos datos como base de conocimiento para realizar comparaciones estadísticas y generar recomendaciones.

  • sample_player_game_stats.csv - Estadísticas de juego de un jugador (por ejemplo, puntos, rebotes, robos, etc., por partido por jugador a lo largo de toda su carrera en la NBA). Emplearemos este conjunto de datos para realizar agregaciones. (Nota: Estos son datos simulados, pregenerados para fines demo y no provenientes de fuentes oficiales de la NBA.)
  • playerAndTeamInfo.js - Sustituye los metadatos de jugadores y equipos que normalmente proporcionaría una llamada a la API para que el agente pueda relacionar los nombres de jugadores y equipos con IDs. Como usamos datos de muestra, no queremos la sobrecarga de buscar desde una API externa, así que codificamos de forma fija algunos valores que el agente puede referenciar.

Implementación:

  1. Mientras estés en el directorio backend/lib , crea un archivo llamado playerDataIngestion.js.
  2. Configura las importaciones, resuelve la ruta del archivo CSV y configura el análisis sintáctico. De nuevo, como estamos usando ESM, necesitamos reconstruir __dirname para resolver el camino hacia el CSV de muestra. Además, importaremos Node.js módulos incorporados, fs y readline, para analizar el archivo CSV dado línea por línea.

Esto te prepara para leer y analizar eficientemente el CSV cuando lleguemos al paso de la ingestión masiva.

3. Crear un índice con el mapeo adecuado. Aunque Elasticsearch puede inferir automáticamente los tipos de campos con mapeo dinámico, queremos ser explícitos aquí para que cada estadística se trate como un campo numérico. Esto es importante porque usaremos estos campos para agregaciones más adelante. También queremos usar el tipo float para estadísticas como puntos, rebotes, etc., para cerciorarnos de incluir valores decimales. Finalmente, queremos agregar la propiedad de mapeo dynamic: 'strict' para que Elasticsearch no mapee dinámicamente campos no reconocidos. 

4. Agregar la función para ingirte en masa los datos CSV en tu índice de Elasticsearch. Dentro del bloque de código, saltamos la línea de cabecera. Luego, divide cada elemento de línea por una coma y empújalos en el objeto documento. Este paso también los limpia y cerciora que sean del tipo adecuado. A continuación, enviamos los documentos al array bulkBody junto con la información del índice, que servirá como carga útil para la ingestión masiva en Elasticsearch.

5. Luego, podemos usar la API Bulk de Elasticsearch con elasticClient.bulk() para ingirse varios documentos en una sola solicitud. La gestión de errores a continuación está estructurada para darte un recuento de cuántos documentos no se ingirieron y cuántos fueron exitosos.

6. Ejecuta la función main() a continuación para ejecutar secuencialmente las funciones createIndex() y bulkIngestCsv() .

Si ves un registro de consola que indique que la ingesta masiva fue exitosa, realiza una comprobación rápida en tu índice de Elasticsearch para ver si los documentos realmente se ingirieron con éxito.

Paso 5: Definición de agregaciones de Elasticsearch y consolidación

Estas serán las funciones principales que se emplearán cuando definamos las herramientas para el Agente de IA para comparar las estadísticas de los jugadores entre sí.

1. Navega al directorio backend/lib y crea un archivo llamado elasticAggs.js.

2. Agregar la consulta siguiente para calcular los promedios históricos de un jugador frente a un oponente específico. Esta consulta emplea un filtro bool con 2 condiciones: una que coincide con player_id y otra que coincide con la opponent_team_id, para recuperar solo los juegos relevantes. No necesitamos devolver ningún documento, solo nos importan las agregaciones, así que establecemos size:0. Bajo el bloque aggs , ejecutamos múltiples agregaciones métricas en paralelo en campos como points, rebounds, assists, steals, blocks y fg_percentage para calcular sus valores medios. Los LLMs pueden ser impredecibles con los cálculos y esto transfiere ese proceso a Elasticsearch, cerciorando que nuestro asistente de IA de la NBA tenga acceso a datos precisos.

3. Para calcular los promedios de temporada de un jugador frente a un oponente específico, usaremos prácticamente la misma consulta que la histórica. La única diferencia en esta consulta es que el filtro bool tiene una condición adicional para game_date. El game_date del campo tiene que estar dentro del rango de la temporada actual de la NBA. En este caso, el rango está entre 2024-10-01 y 2025-06-30. Esta condición adicional a continuación garantiza que las agregaciones que sigan aislarán solo los partidos de esta temporada.

Paso 6: Utilidad de comparación de jugadores

Para mantener nuestro código modular y mantenible, crearemos un archivo de utilidad que consolide las funciones auxiliares de metadatos y las agregaciones de Elasticsearch. Esto alimentará la herramienta principal que emplea el agente. Más sobre eso más adelante:

1. Crear un nuevo archivo comparePlayers.js en el directorio backend/lib .

2. Agregar la función siguiente para consolidar los asistentes de metadatos y la lógica de agregación de Elasticsearch en una única función que alimente la herramienta principal empleada por el agente.

Paso 7: Construir el agente

Ahora que creaste el frontend y el backend de estructura, absorbiste datos de los partidos de la NBA y establecido una conexión con Elasticsearch, podemos empezar a juntar todas las piezas para construir el agente.

Definición del agente

1. Navega al archivo index.ts dentro del directorio backend/src/mastra/agents y agrega la definición del agente. Puedes especificar campos como:

  • Nombre: Dale a tu agente un nombre que se use como referencia cuando te llamen en el frontend.
  • Instrucciones/prompt del sistema: Un prompt del sistema proporciona al LLM el contexto inicial y las reglas a seguir durante la interacción. Es similar al prompt que los usuarios envían a través del cuadro de chat, pero este se da antes de cualquier entrada del usuario. De nuevo, esto cambiará según el modelo que elijas.
  • Modelo: ¿Qué LLM usar (Mastra soporta OpenAI, Anthropic, modelos locales, etc.).
  • Herramientas: Una lista de funciones de la herramienta que el agente puede llamar.
  • Memoria: (Opcional) si queremos que el agente recuerde el historial de conversaciones, etc. Para simplificar, podemos empezar sin memoria persistente, aunque Mastra la admite.


Definición de herramientas

  1. Navega al archivo index.ts dentro del directorio backend/src/mastra/tools .
  2. Instala Zod usando el comando:

3. Agregar definiciones de herramientas. Ten en cuenta que importamos la función dentro del archivo comparePlayers.js como la función principal que el agente usará al llamar a esta herramienta. Usando la función createTool() de Mastra, registraremos nuestro playerComparisonTool. Los campos incluyen:

  • id: Esta es una descripción en lenguaje natural para ayudar al agente a entender qué hace la herramienta.
  • input schema: Para definir la forma de la entrada de la herramienta, Mastra emplea el esquema Zod , que es una biblioteca de validación de esquema TypeScript. Zod ayuda cerciorar de que el agente reciba entradas estructuradas correctamente y evita que la herramienta se ejecute si la estructura de entrada no coincide.
  • description: Esta es una descripción en lenguaje natural para ayudar al agente a entender cuándo llamar y usar la herramienta.
  • execute: La lógica que se ejecuta cuando se llama a la herramienta. En nuestro caso, estamos usando una función auxiliar importada para devolver estadísticas de rendimiento.

Adición de middleware para manejar CORS

Agregar middleware en el servidor Mastra para manejar CORS. Dicen que hay tres cosas en la vida que no puedes evitar: la muerte, los impuestos, y para los desarrolladores web es el CORS. En resumen, el Intercambio de Recursos entre Orígenes es una función de seguridad en el navegador que bloquea al frontend para que no haga peticiones a un backend que se ejecuta en otro dominio o puerto. Aunque ejecutamos tanto el backend como el frontend en localhost, usan puertos diferentes, lo que activa la política CORS. Necesitamos agregar el middleware especificado en la documentación de Mastra para que nuestro backend permita esas peticiones desde el frontend.

1. Navega al archivo index.ts dentro del directorio backend/src/mastra y agrega la configuración para CORS:

  • origin: ['http://localhost:5173']
    • Permite solicitudes solo desde esta dirección (dirección predeterminada de Vite)
  • allowMethods: ["GET", "POST"]
    • Métodos HTTP que están permitidos. La mayoría de las veces, será usando POST.
  • allowHeaders: ["Content-Type", "Authorization", "x-mastra-client-type, "x-highlight-request", "traceparent"],
    • Estos deciden qué encabezados personalizados pueden usar en las solicitudes

Paso 8: Integración del frontend

Este componente React proporciona una interfaz de chat sencilla que se conecta al agente Mastra AI usando el gancho useChat() de @ai-sdk/react. También vamos a usar este gancho para mostrar el uso de tokens, llamadas a herramientas y para renderizar la conversación. En el prompt del sistema anterior, también pedimos al agente que genere la respuesta en markdown, así que usaremos react-markdown para formatear correctamente la respuesta.

1. Mientras estés en el directorio frontend, instala el paquete @ai-sdk/react para usar el hook useChat().

2. Mientras estés en el mismo directorio, instala React Markdown para que podamos formatear correctamente la respuesta que genera el agente.

3. Implementar useChat(). Este gancho gestionará la interacción entre tu frontend y el backend de tu agente de IA. Gestiona el estado del mensaje, la entrada del usuario, el estado y te proporciona ganchos de ciclo de vida para fines de observabilidad. Las opciones que descartamos incluyen:

  • api: Esto define el punto final de tu Mastra AI Agent. Por defecto se pone en el puerto 4111 y también queremos agregar la ruta que soporta respuestas en streaming.
  • onToolCall: Esto se ejecuta cada vez que el agente llama a una herramienta; Lo estamos usando para rastrear qué herramientas está llamando nuestro agente.
  • onFinish: Esto se ejecuta después de que el agente complete una respuesta completa. Aunque activamos el streaming, onFinish seguirá ejecutar luego de recibir el mensaje completo y no luego de cada chunk. Aquí, lo estamos usando para rastrear nuestro uso de tokens. Esto puede ser útil para monitorizar los costos de los LLM y optimizarlos.

4. Por último, ve al componente ChatUI.jsx en el directorio frontend/components para crear la interfaz que mantenga nuestra conversación. A continuación, envuelve la respuesta en un componente ReactMarkdown para formatear correctamente la respuesta del agente.

Paso 9: Ejecutar la aplicación

¡Felicidades! Ahora estás listo para ejecutar la aplicación. Sigue estos pasos para empezar tanto el backend como el frontend.

  1. En una ventana de terminal, empezando desde el directorio raíz, navega hasta el directorio backend e inicia el servidor Mestra:

2. En otra ventana de terminal, empezando desde el directorio raíz, navega hasta el directorio frontend e inicia la aplicación React:

3. Ve a tu navegador y navega a:

http://localhost:5173

Deberías poder ver la interfaz del chat. Prueba estos ejemplos de prompts:

  • "Compara a LeBron James y Stephen Curry"
  • "¿A quién debería elegir entre Jayson Tatum y Luka Doncic?"

Qué sigue: Hacer que el agente sea más inteligente

Para que el asistente sea más agenciado y las recomendaciones más perspicaces, agregaré algunas mejoras clave en la próxima iteración.

Búsqueda semántica de noticias de la NBA

Hay un montón de factores que pueden afectar al rendimiento de los jugadores, muchos de los cuales no aparecen en las estadísticas brutas. Cosas como reportes de lesiones, cambios en la alineación o incluso análisis postpartido, solo se pueden encontrar en artículos de prensa. Para captar este contexto adicional, agregaré capacidades de búsqueda semántica para que el agente pueda recuperar artículos relevantes de la NBA e incluir esa narrativa en sus recomendaciones.

Búsqueda dinámica con el servidor MCP de Elasticsearch

MCP (Model Context Protocol) se está convirtiendo rápidamente en el estándar para cómo los agentes se conectan a fuentes de datos. Migraré la lógica de búsqueda al servidor Elasticsearch MCP, que permite al agente construir consultas dinámicamente en lugar de depender de funciones de búsqueda predefinidas que proporcionamos. Esto nos permite emplear más flujos de trabajo en lenguaje natural y reduce la necesidad de escribir manualmente cada consulta de búsqueda. Descubre más sobre el servidor MCP de Elasticsearch y el estado actual del ecosistema aquí.

Estos cambios ya están en marcha, ¡estad atentos!

Conclusión

En este blog, creamos un asistente RAG agente que ofrece recomendaciones personalizadas para tu equipo de baloncesto de fantasía usando JavaScript, Mastra y Elasticsearch. Cubrimos lo siguiente:

  • Fundamentos del RAG agente y cómo combinar la autonomía de un agente de IA con las herramientas para usar RAG de forma eficaz puede conducir a agentes más matizados y dinámicos.
  • Elasticsearch y cómo sus capacidades de almacenamiento de datos y poderosas agregaciones nativas lo convierten en un gran socio como base de conocimiento para un LLM.
  • El framework Mastra y cómo simplifica la construcción de estos agentes para desarrolladores en el ecosistema javaScript.

Tanto si eres un fanático del baloncesto, explorando cómo crear agentes de IA, o ambos como yo, espero que este blog te dio algunos cimientos para empezar. El repositorio completo está disponible en GitHub, siéntete libre de clonar y trastear. ¡Ahora, gana esa liga de fantasía!

Contenido relacionado

¿Estás listo para crear experiencias de búsqueda de última generación?

No se logra una búsqueda suficientemente avanzada con los esfuerzos de uno. Elasticsearch está impulsado por científicos de datos, operaciones de ML, ingenieros y muchos más que son tan apasionados por la búsqueda como tú. Conectemos y trabajemos juntos para crear la experiencia mágica de búsqueda que te dará los resultados que deseas.

Pruébalo tú mismo