La investigación profunda en inteligencia artificial no es un modelo monolítico único, sino más bien un proceso, un flujo de trabajo iterativo que implica buscar, leer y razonar hasta que se encuentra una respuesta. Los sistemas propietarios de OpenAI, como los que impulsan ChatGPT o GPT-4, utilizan complejas canalizaciones que refinan continuamente las respuestas. Ahora imagina poder construir un sistema similar utilizando herramientas de código abierto. Este artículo explica cómo recrear un sistema de Investigación Profunda utilizando el proyecto jina-ai/node-DeepResearch. Desglosaremos el código, detallaremos cada componente y te mostraremos cómo configurar y ampliar el sistema.
1. Descripción general y propósito
DeepResearch se basa en una idea simple pero poderosa:
Sigue buscando y leyendo páginas web hasta encontrar la respuesta (o exceder el presupuesto de tokens).
El sistema toma una consulta (por ejemplo, "¿quién es más grande? cohere, jina ai, voyage?") y entra en un bucle. En cada paso, el agente (un módulo inteligente) decide una acción. Podría buscar nuevas palabras clave, leer el contenido de las URL, reflexionar generando preguntas de seguimiento o proporcionar una respuesta si está seguro. Este ciclo iterativo continúa hasta que la respuesta es definitiva o se excede el presupuesto de tokens (un proxy para los recursos computacionales).
Instalación y configuración
Antes de sumergirte en el código, debes instalar las dependencias necesarias y configurar tus claves API. El proyecto utiliza Gemini para el modelado del lenguaje, Brave o DuckDuckGo para la búsqueda web y Jina Reader para obtener contenido de páginas web. Aquí te mostramos cómo configurar el proyecto:
export GEMINI_API_KEY=... # para la API de Gemini, pregunta a Han
export JINA_API_KEY=jina_... # clave API gratuita de Jina, obténla de https://jina.ai/reader
export BRAVE_API_KEY=... # opcional; si no se proporciona, se utiliza la búsqueda de DuckDuckGo por defecto
git clone https://github.com/jina-ai/node-DeepResearch.git
cd node-DeepResearch
npm install
El README incluso proporciona ejemplos para ejecutar el sistema con diferentes consultas:
- Consulta simple:
npm run dev "1+1="
onpm run dev "¿cuál es la capital de Francia?"
- Consulta de varios pasos:
npm run dev "¿cuáles son las últimas noticias de Jina AI?"
npm run dev "¿cuál es la cuenta de Twitter del fundador de jina ai?"
- Consulta ambigua, tipo investigación:
npm run dev "¿quién es más grande? cohere, jina ai, voyage?"
npm run dev "¿quién será el presidente de EE. UU. en 2028?"
npm run dev "¿cuál debería ser la estrategia de jina ai para 2025?"
Además de una interfaz de línea de comandos, el proyecto también incluye una API de servidor web que expone puntos finales para enviar consultas y transmitir actualizaciones de progreso.
2. Arquitectura y componentes clave
Desglosemos los principales componentes del sistema explorando los archivos principales:
2.1 agent.ts – La lógica central
El archivo agent.ts
es el corazón del sistema. Implementa la lógica para el ciclo de "investigación profunda": generar indicaciones, decidir acciones e iterar a través de los pasos de búsqueda, lectura, reflexión y respuesta.
Elementos clave en agent.ts:
Importaciones y configuración:
El archivo comienza importando varias herramientas y bibliotecas:
- GoogleGenerativeAI se utiliza para la generación de lenguaje.
- readUrl de
./tools/read
obtiene y procesa el contenido de las páginas web. - duckSearch y braveSearch proporcionan capacidades de búsqueda externas.
- Funciones de utilidad como rewriteQuery, dedupQueries, evaluateAnswer y analyzeSteps ayudan a refinar las consultas y evaluar las respuestas.
- Los valores de configuración (claves API, presupuestos de tokens y configuraciones de modelos) se importan desde
config.ts
. - Las utilidades de Token y Action Tracker supervisan el uso de tokens y el estado del progreso del agente.
- Finalmente, el archivo importa tipos (por ejemplo,
StepAction
,ResponseSchema
) definidos entypes.ts
.
Función de suspensión:
async function sleep(ms: number) {
const seconds = Math.ceil(ms / 1000);
console.log(`Waiting ${seconds}s...`);
return new Promise(resolve => setTimeout(resolve, ms));
}
Esta función auxiliar se utiliza para retrasar las operaciones, lo cual es útil para evitar la limitación de velocidad al llamar a las API externas.
Generación de esquemas:
La función getSchema
define el esquema JSON para la respuesta del agente. Construye dinámicamente un esquema que incluye propiedades para:
- search: Requiere una
searchQuery
basada en palabras clave. - answer: Especifica que una respuesta final debe incluir texto en lenguaje natural y referencias de apoyo (citas exactas y URL).
- reflect: Enumera las subpreguntas aclaratorias para llenar los vacíos de conocimiento.
- visit: Contiene URL de destino para leer contenido externo.
Al aplicar un esquema JSON estricto, la salida del agente sigue siendo coherente y legible por máquina.
Generación de indicaciones:
La función getPrompt
crea una indicación detallada que se envía al modelo de lenguaje. Agrega varias secciones:
- Header: Incluye la fecha actual y la pregunta original.
- Context and Knowledge: Se incluyen todas las acciones previas y el conocimiento intermedio recopilado.
- Unsuccessful Attempts: Si las acciones anteriores no lograron producir una respuesta definitiva, esos fallos (con razones y mejoras) se registran.
- Actions: Se muestra una lista de posibles acciones. Dependiendo de los indicadores (como
allowSearch
,allowRead
, etc.), enumera las operaciones permitidas. En el "Modo Bestia", las instrucciones instan al agente a esforzarse al máximo para producir una respuesta, incluso si persiste la incertidumbre.
Esta indicación en capas guía al modelo de IA generativa para que "piense" paso a paso y seleccione una acción a la vez.
Bucle principal en getResponse:
La función getResponse
es el núcleo del bucle iterativo del agente. Configura el contexto inicial:
- Trackers: Se utilizan dos rastreadores: un TokenTracker para supervisar el número de tokens utilizados (evitando que el sistema exceda su presupuesto) y un ActionTracker para rastrear cada paso y sus resultados.
- Gaps and Knowledge: Comienza con una "brecha" (la pregunta original) y luego agrega preguntas intermedias si el sistema necesita reflexionar sobre su razonamiento.
Dentro de un bucle while, el agente:
- Espera (usando la función de suspensión) para evitar los límites de velocidad de la API.
- Genera una indicación basada en el contexto actual.
- Llama al modelo generativo (a través de GoogleGenerativeAI) para producir una respuesta.
- Analiza la respuesta JSON para determinar qué acción se tomó (responder, reflexionar, buscar o visitar).
- Dependiendo de la acción:
- Answer: Evalúa la respuesta y, si es definitiva, finaliza el bucle.
- Reflect: Procesa las subpreguntas para llenar los vacíos de conocimiento.
- Search: Reescribe la consulta de búsqueda, elimina las palabras clave utilizadas anteriormente y recupera nuevas URL de DuckDuckGo o Brave.
- Visit: Lee el contenido de las URL proporcionadas y actualiza la base de conocimiento.
Si el bucle se queda sin presupuesto o se producen demasiados intentos fallidos, el sistema entra en "Modo Bestia", donde se realiza un intento final y agresivo de responder.
Almacenamiento de contexto:
La función storeContext
escribe la indicación actual y varios estados de memoria (contexto, consultas, preguntas y conocimiento recopilado) en archivos. Este proceso de archivo ayuda a la depuración y permite un análisis más profundo del proceso de toma de decisiones.
Ejecución final:
La función main()
al final de agent.ts
utiliza el argumento de la línea de comandos (la consulta), invoca getResponse
e imprime la respuesta final junto con un resumen del uso de tokens.
2.2 config.ts – Configuración del entorno
El archivo config.ts
es donde se definen las configuraciones del entorno y del modelo:
- Variables de entorno: Utilizando
dotenv
, carga las claves API para Gemini, Jina y Brave. También admite la configuración de un proxy HTTPS. - Search Provider: El sistema selecciona dinámicamente el proveedor de búsqueda en función de si se proporciona una clave API de Brave; si no, se utiliza DuckDuckGo por defecto.
- Model Configurations: El archivo configura configuraciones de modelo predeterminadas y específicas para diversas tareas, como la reescritura de consultas, la deduplicación y la evaluación. Por ejemplo, el modelo generativo del agente está configurado con una temperatura de 0.7 para equilibrar la creatividad y el determinismo.
- Token Budget and Delay: La constante
STEP_SLEEP
se establece en 1000 milisegundos, lo que garantiza una pausa de un segundo entre los pasos.
Este archivo de configuración facilita el cambio de configuración y la adaptación del sistema a diferentes entornos o comportamientos del modelo.
2.3 server.ts – La API del servidor web
Para permitir a los usuarios interactuar con DeepResearch a través de solicitudes HTTP, el sistema incluye un servidor simple basado en Express en server.ts
. Este archivo configura puntos finales que gestionan el envío de consultas y transmiten actualizaciones de progreso en tiempo real.
Puntos clave en server.ts:
Configuración de Express:
El servidor utiliza Express y CORS para admitir solicitudes de origen cruzado. Escucha en el puerto 3000 (o un puerto especificado en el entorno).
Punto final de consulta (POST /api/v1/query
):
- Los clientes envían una carga útil JSON que contiene la consulta, el presupuesto de tokens y el número máximo de intentos fallidos permitidos.
- El servidor crea un nuevo rastreador (para el uso de tokens y el estado de la acción) y asigna un
requestId
único. - La solicitud se procesa de forma asíncrona llamando a
getResponse
. - Una vez completada, la respuesta final se almacena y el progreso se emite utilizando un
EventEmitter
.
Punto final de transmisión (GET /api/v1/stream/:requestId
):
- Este punto final utiliza eventos enviados por el servidor (SSE) para enviar continuamente actualizaciones al cliente.
- A medida que el agente realiza acciones (buscar, reflexionar, visitar, responder), se emiten eventos de progreso. Cada evento incluye información del paso actual, uso de tokens y detalles de la acción.
- Esto permite a los clientes supervisar el proceso de investigación en tiempo real.
Almacenamiento y recuperación de tareas:
El servidor escribe los resultados de las tareas en el sistema de archivos (en un directorio tasks
) y proporciona un punto final (GET /api/v1/task/:requestId
) para recuperar un resultado almacenado.
Este componente del servidor web hace que el agente de investigación sea accesible a través de HTTP, lo que permite tanto experimentos interactivos como la integración en sistemas más grandes.
2.4 test-duck.ts – Una utilidad para probar la búsqueda
El archivo test-duck.ts
es un script independiente que utiliza Axios para enviar una solicitud HTTP GET a una API externa (en este caso, jsonplaceholder.typicode.com
) como prueba. Aunque su función principal es verificar que las solicitudes HTTP funcionen correctamente (incluida la configuración de los encabezados adecuados y el manejo de errores), sirve como ejemplo de cómo se gestionan las solicitudes externas dentro del sistema. En una configuración más compleja, se utilizan patrones similares al consultar API de búsqueda como DuckDuckGo o Brave.
2.5 types.ts – Definición de estructuras de datos coherentes
El archivo types.ts
define todos los tipos personalizados utilizados en todo el proyecto:
Action Types:
Estos incluyen las diversas acciones que el agente puede realizar:
- SearchAction: Contiene una cadena
searchQuery
. - AnswerAction: Requiere una cadena
answer
yreferences
de apoyo. - ReflectAction: Incluye una matriz de
questionsToAnswer
. - VisitAction: Contiene una lista de
URLTargets
.
Response Types:
El archivo define respuestas estructuradas para resultados de búsqueda, lectura de URL, evaluación, análisis de errores y más. Esto ayuda a mantener la coherencia y garantiza que cada módulo interprete los datos de la misma manera.
Schema Types:
Las definiciones de esquema JSON garantizan que las respuestas generadas por el modelo de lenguaje se ajusten estrictamente al formato esperado. Esto es crucial para el procesamiento posterior.
Tracker Context:
También se definen tipos personalizados para los rastreadores de tokens y acciones, que se utilizan para supervisar el estado de la conversación y el proceso de investigación.
3. El proceso iterativo de investigación profunda
El sistema general sigue un proceso metódico e iterativo que imita la forma en que podría trabajar un investigador humano:
Initialization:
El proceso comienza con la pregunta original, que se agrega a una lista de "brechas" (es decir, las incógnitas que deben llenarse).
Prompt Generation:
El agente crea una indicación utilizando la pregunta actual, el contexto anterior, el conocimiento recopilado e incluso los intentos fallidos. Esta indicación se envía luego al modelo de IA generativa.
Action Selection:
Basándose en la salida del modelo, el agente selecciona una de varias acciones:
- Search: Formular una nueva consulta para recopilar más datos.
- Visit: Recuperar contenido detallado de una URL específica.
- Reflect: Generar subpreguntas aclaratorias para abordar cualquier vacío de conocimiento.
- Answer: Proporcionar una respuesta final si la información se considera definitiva.
Context Update:
Cada paso actualiza los rastreadores internos (uso de tokens y estado de la acción) y archiva el estado actual en archivos. Esto garantiza la transparencia y permite la depuración o la revisión posterior.
Evaluation and Looping:
Cuando se propone una respuesta, un paso de evaluación comprueba si es definitiva. Si no, el sistema almacena los detalles del intento fallido y ajusta su estrategia. El ciclo continúa hasta que se encuentra una respuesta satisfactoria o se agota el presupuesto de tokens.
Beast Mode:
Si los pasos normales no logran producir una respuesta definitiva dentro de las limitaciones, el sistema entra en "Modo Bestia". En este modo, la IA generativa se ve obligada a producir una respuesta basada en el contexto acumulado, incluso si eso significa hacer una conjetura fundamentada.
4. Progreso y comentarios en tiempo real
Una característica integral del sistema DeepResearch es su mecanismo de retroalimentación en tiempo real. A través del punto final de transmisión del servidor web:
- Los clientes reciben actualizaciones de progreso que detallan qué acción se tomó, las estadísticas de uso de tokens y el estado actual del rastreador de acciones.
- Los eventos de progreso (como se muestra en los ejemplos de README) incluyen tanto el proceso de pensamiento del agente como detalles como el paso actual y el desglose de tokens.
- Este bucle de retroalimentación en vivo es invaluable para la depuración, la supervisión del uso de recursos y la comprensión de cómo está razonando el sistema.
Por ejemplo, un evento de progreso podría verse así:
data: {
"type": "progress",
"trackers": {
"tokenUsage": 74950,
"tokenBreakdown": {
"agent": 64631,
"read": 10319
},
"actionState": {
"action": "search",
"thoughts": "El texto menciona varios inversores en Jina AI, pero no especifica los porcentajes de propiedad. Se necesita una búsqueda directa.",
"URLTargets": [],
"answer": "",
"questionsToAnswer": [],
"references": [],
"searchQuery": "Porcentajes de propiedad de los inversores de Jina AI"
},
"step": 7,
"badAttempts": 0,
"gaps": []
}
}
Este informe de progreso detallado permite a los desarrolladores ver cómo evoluciona el razonamiento del agente con el tiempo, proporcionando información sobre los éxitos y las áreas que necesitan mejoras.
5. Ampliación y personalización de DeepResearch
La naturaleza de código abierto de este proyecto significa que puedes adaptar el sistema a tus necesidades. Aquí hay algunas ideas para ampliar DeepResearch:
Custom Search Providers:
Podrías integrar proveedores de búsqueda adicionales o personalizar el proceso de reescritura de consultas para búsquedas específicas del dominio.
Enhanced Reading Modules:
Si necesitas un procesamiento de texto más detallado, puedes integrar modelos NLP alternativos o ajustar el componente Jina Reader para manejar nuevos tipos de contenido.
Improved Evaluation:
El módulo de evaluación actualmente comprueba si una respuesta es definitiva. Podrías ampliar esto para incorporar métricas más matizadas, como el análisis de sentimientos o los algoritmos de verificación de hechos.
User Interface:
Si bien el sistema actual utiliza una interfaz de línea de comandos y un servidor web simple para transmitir eventos, podrías crear una interfaz web o móvil completa para sesiones de investigación interactivas.
Scalability Enhancements:
La implementación actual se ejecuta como un servicio de un solo nodo. Para el uso en producción, considera la posibilidad de contenerizar la aplicación e implementarla utilizando Kubernetes u otra plataforma de orquestación para gestionar el alto tráfico y el procesamiento distribuido.
6. Seguridad, rendimiento y mejores prácticas
Al implementar un sistema impulsado por IA como DeepResearch, hay algunas consideraciones adicionales:
API Key Management:
Asegúrate de que tus claves API (para Gemini, Jina y Brave) estén almacenadas de forma segura y nunca codificadas en tu código fuente. Se recomiendan las variables de entorno y las bóvedas seguras.
Rate Limiting:
La función sleep
integrada ayuda a evitar la limitación de velocidad al retrasar las solicitudes sucesivas. Sin embargo, considera la posibilidad de implementar mecanismos adicionales de limitación de velocidad en el servidor o en el nivel de la puerta de enlace API.
Data Validation:
Valida estrictamente las consultas y respuestas de entrada. El esquema JSON definido en el agente ayuda, pero también debes validar las solicitudes HTTP entrantes para evitar entradas maliciosas.
Error Handling:
El manejo robusto de errores (como se ve en el código del servidor y test-duck.ts) es fundamental. Esto garantiza que los fallos inesperados de la API o las respuestas mal formadas no bloqueen el sistema.
Resource Monitoring:
El seguimiento del uso de tokens es esencial. Las clases TokenTracker y ActionTracker proporcionan información sobre el consumo de recursos. La supervisión de estas métricas puede ayudar a ajustar el rendimiento del sistema y evitar un uso excesivo.
7. Conclusión
El proyecto DeepResearch de Jina AI ejemplifica cómo se pueden construir procesos de investigación complejos e iterativos utilizando herramientas de código abierto. Al integrar motores de búsqueda, modelos de IA generativa y bucles de razonamiento inteligente, el sistema refina continuamente su respuesta hasta que está seguro, o hasta que se alcanzan los límites de recursos.
En este artículo, exploramos cómo recrear OpenAI Deep Research utilizando un enfoque de código abierto:
- Hablamos de los pasos de instalación y la configuración del entorno.
- Desglosamos los módulos principales, desde la lógica del agente iterativo en
agent.ts
hasta la configuración, la API del servidor web y las definiciones de tipo. - Examinamos el mecanismo de retroalimentación en tiempo real que transmite actualizaciones de progreso, proporcionando transparencia en el proceso de razonamiento.
- Finalmente, analizamos las posibles extensiones, las opciones de personalización y las mejores prácticas para implementar un sistema de este tipo.
Al hacer que estas técnicas de investigación avanzadas estén disponibles como código abierto, proyectos como DeepResearch democratizan el acceso a métodos de IA de vanguardia. Tanto si eres un investigador, un desarrollador o una empresa que busca integrar capacidades de investigación profunda en tus flujos de trabajo, este proyecto sirve como inspiración y como base práctica para construir tu propia solución.
El diseño iterativo, que combina la búsqueda, la lectura, la reflexión y la respuesta en un bucle continuo, garantiza que incluso las consultas ambiguas o complejas se gestionen con múltiples capas de escrutinio. Y con una arquitectura detallada que rastrea el uso de tokens y proporciona retroalimentación en vivo, obtienes información profunda sobre el proceso de razonamiento detrás de cada respuesta.
Si estás ansioso por experimentar, clona el repositorio, configura tu entorno como se describe y ejecuta consultas que van desde la aritmética simple hasta preguntas de investigación multifacéticas. Con un poco de personalización, puedes adaptar el sistema a nuevos dominios e incluso mejorar sus capacidades de razonamiento. Los proyectos de código abierto como este allanan el camino para la innovación impulsada por la comunidad en la investigación de la IA.
Siguiendo este desglose y análisis detallados, puedes recrear y ampliar las ideas detrás de Deep Research de OpenAI de una manera totalmente de código abierto. Tanto si buscas construir sobre la base de código existente como si quieres integrar metodologías similares en tus proyectos, la hoja de ruta es clara: iterar, refinar y superar los límites de la investigación automatizada.