Apidog

Plataforma Colaborativa All-in-one para Desenvolvimento de API

Design de API

Documentação de API

Depuração de API

Mock de API

Testes Automatizados de API

Como Recriar a Pesquisa Profunda da OpenAI, Mas em Código Aberto

@apidog

@apidog

Updated on fevereiro 4, 2025

A profunda pesquisa em inteligência artificial não é um único modelo monolítico—é, na verdade, um processo, um fluxo de trabalho iterativo que envolve pesquisar, ler e raciocinar até que uma resposta seja encontrada. Os sistemas proprietários da OpenAI, como os que alimentam o ChatGPT ou o GPT-4, utilizam pipelines complexos que refinam continuamente as respostas. Agora imagine poder construir um sistema semelhante usando ferramentas de código aberto. Este artigo explica como recriar um sistema de Pesquisa Profunda usando o projeto jina-ai/node-DeepResearch. Vamos destrinchar o código, detalhar cada componente e mostrar como configurar e expandir o sistema.

botão

1. Visão Geral e Propósito

O DeepResearch é construído em torno de uma ideia simples, mas poderosa:

Continue pesquisando e lendo páginas da web até encontrar a resposta (ou exceder o orçamento de tokens).

O sistema recebe uma consulta (por exemplo, "quem é maior? cohere, jina ai, voyage?") e entra em um loop. A cada passo, o agente (um módulo inteligente) decide sobre uma ação. Ele pode buscar novas palavras-chave, ler o conteúdo de URLs, refletir gerando perguntas adicionais, ou fornecer uma resposta se estiver certo. Esse ciclo iterativo continua até que a resposta seja definitiva ou até que o orçamento de tokens (um proxy para recursos computacionais) seja excedido.

Instalação e Configuração

Antes de mergulhar no código, você precisa instalar as dependências necessárias e definir suas chaves de API. O projeto utiliza o Gemini para modelagem de linguagem, Brave ou DuckDuckGo para busca na web, e o Jina Reader para buscar conteúdo de páginas da web. Veja como configurar o projeto:

export GEMINI_API_KEY=...  # para a API Gemini, pergunte ao Han
export JINA_API_KEY=jina_...  # chave de API Jina gratuita, obtenha em https://jina.ai/reader
export BRAVE_API_KEY=...  # opcional; se não fornecido, padrão para busca DuckDuckGo

git clone https://github.com/jina-ai/node-DeepResearch.git
cd node-DeepResearch
npm install

O README fornece até exemplos para executar o sistema com diferentes consultas:

  • Consulta Simples:
    npm run dev "1+1=" ou npm run dev "qual é a capital da França?"
  • Consulta Multistep:
    npm run dev "quais são as últimas notícias da Jina AI?"
    npm run dev "qual é a conta do twitter do fundador da jina ai"
  • Consulta Ambígua, Semelhante a Pesquisa:
    npm run dev "quem é maior? cohere, jina ai, voyage?"
    npm run dev "quem será o presidente dos EUA em 2028?"
    npm run dev "qual deve ser a estratégia da jina ai para 2025?"

Além de uma interface de linha de comando, o projeto também inclui uma API de servidor web que expõe endpoints para submeter consultas e transmitir atualizações de progresso.


2. Arquitetura e Componentes Chave

Vamos detalhar os principais componentes do sistema explorando os arquivos centrais:

2.1 agent.ts – A Lógica Central

O arquivo agent.ts é o coração do sistema. Ele implementa a lógica para o ciclo de "pesquisa profunda": gerando prompts, decidindo ações e iterando através das etapas de busca, leitura, reflexão e resposta.

Elementos Principais em agent.ts:

Imports e Configuração:

O arquivo começa importando várias ferramentas e bibliotecas:

  • GoogleGenerativeAI é utilizado para geração de linguagem.
  • readUrl de ./tools/read busca e processa conteúdo de páginas da web.
  • duckSearch e braveSearch fornecem capacidades de busca externa.
  • Funções utilitárias como rewriteQuery, dedupQueries, evaluateAnswer, e analyzeSteps ajudam a refinar consultas e avaliar respostas.
  • Valores de configuração (chaves de API, orçamentos de tokens, e configurações de modelos) são importados de config.ts.
  • Utilitários de Token e Rastreadores de Ação monitoram o uso de tokens e o estado do progresso do agente.
  • Finalmente, o arquivo importa tipos (por exemplo, StepAction, ResponseSchema) definidos em types.ts.

Função Sleep:

async function sleep(ms: number) {
  const seconds = Math.ceil(ms / 1000);
  console.log(`Aguardando ${seconds}s...`);
  return new Promise(resolve => setTimeout(resolve, ms));
}

Essa função auxiliar é usada para atrasar operações—útil para evitar limites de taxa ao chamar APIs externas.

Geração de Schema:

A função getSchema define o schema JSON para a resposta do agente. Ela constrói dinamicamente um schema que inclui propriedades para:

  • search: Requer uma searchQuery baseada em palavras-chave.
  • answer: Especifica que uma resposta final deve incluir texto em linguagem natural e referências de apoio (citações exatas e URLs).
  • reflect: Lista sub-perguntas esclarecedoras para preencher lacunas de conhecimento.
  • visit: Contém alvos de URL para leitura de conteúdo externo.

Ao garantir um schema JSON rigoroso, a saída do agente permanece consistente e legível por máquina.

Geração de Prompt:

A função getPrompt cria um prompt detalhado que é enviado ao modelo de linguagem. Ele agrega várias seções:

  • Cabeçalho: Inclui a data atual e a pergunta original.
  • Contexto e Conhecimento: Quaisquer ações anteriores e conhecimento intermediário coletado são incluídos.
  • Tentativas Não-Sucedidas: Se ações anteriores falharam em produzir uma resposta definitiva, essas falhas (com razões e melhorias) são registradas.
  • Ações: Uma lista de possíveis ações é mostrada. Dependendo de flags (como allowSearch, allowRead, etc.), enumera as operações permitidas. No "Modo Fera", as instruções instam o agente a fazer o possível para produzir uma resposta, mesmo que permaneçam incertezas.

Este prompt em camadas guia o modelo de IA generativa a "pensar" passo a passo e selecionar uma ação de cada vez.

Loop Principal na getResponse:

A função getResponse é o núcleo do loop iterativo do agente. Ela configura o contexto inicial:

  • Rastreadores: Dois rastreadores são usados—um TokenTracker para monitorar o número de tokens usados (impedindo que o sistema exceda seu orçamento) e um ActionTracker para rastrear cada passo e seus resultados.
  • Lacunas e Conhecimento: Começa com uma "lacuna" (a pergunta original) e adiciona perguntas intermediárias se o sistema precisar refletir sobre seu raciocínio.

Dentro de um loop while, o agente:

  • Espera (usando a função sleep) para evitar limites de taxa da API.
  • Gera um prompt com base no contexto atual.
  • Chama o modelo generativo (via GoogleGenerativeAI) para produzir uma resposta.
  • Analisa a resposta JSON para determinar qual ação foi tomada (responder, refletir, buscar ou visitar).
  • Dependendo da ação:
  • Resposta: Avalia a resposta e, se definitiva, encerra o loop.
  • Refletir: Processa sub-perguntas para preencher lacunas de conhecimento.
  • Busca: Reescreve a consulta de busca, deduplica palavras-chave previamente usadas e recupera novas URLs de DuckDuckGo ou Brave.
  • Visitar: Lê o conteúdo das URLs fornecidas e atualiza a base de conhecimento.

Se o loop esgotar o orçamento ou muitas tentativas ruins ocorrerem, o sistema entra no "Modo Fera", onde é feita uma última tentativa agressiva de responder.

Armazenamento de Contexto:

A função storeContext escreve o prompt atual e vários estados de memória (contexto, consultas, perguntas e conhecimento coletado) em arquivos. Esse processo de arquivamento ajuda na depuração e permite uma análise posterior do processo de tomada de decisão.

Execução Final:

A função main() no final de agent.ts utiliza o argumento de linha de comando (a consulta), invoca getResponse e imprime a resposta final juntamente com um resumo do uso de tokens.


2.2 config.ts – Configurando o Ambiente

O arquivo config.ts é onde as configurações do ambiente e do modelo estão definidas:

  • Variáveis de Ambiente: Usando dotenv, carrega as chaves de API para Gemini, Jina e Brave. Também suporta a configuração de um proxy HTTPS.
  • Provedor de Busca: O sistema seleciona dinamicamente o provedor de busca com base na disponibilidade de uma chave de API Brave; caso contrário, o padrão é DuckDuckGo.
  • Configurações do Modelo: O arquivo configura configurações padrão e específicas para várias tarefas, como reescrita de consultas, deduplicação e avaliação. Por exemplo, o modelo generativo do agente é configurado com uma temperatura de 0.7 para equilibrar criatividade e determinismo.
  • Orçamento de Tokens e Atraso: A constante STEP_SLEEP é definida para 1000 milissegundos, garantindo uma pausa de um segundo entre as etapas.

Esse arquivo de configuração facilita a alteração de configurações e a adaptação do sistema a diferentes ambientes ou comportamentos do modelo.


2.3 server.ts – A API do Servidor Web

Para permitir que os usuários interajam com o DeepResearch por meio de solicitações HTTP, o sistema inclui um simples servidor baseado em Express no server.ts. Este arquivo configura endpoints que lidam com a submissão de consultas e transmissão de atualizações de progresso em tempo real.

Pontos Chave em server.ts:

Configuração do Express:

O servidor utiliza Express e CORS para suportar solicitações cross-origin. Ele escuta na porta 3000 (ou em uma porta especificada no ambiente).

Endpoint de Consulta (POST /api/v1/query):

  • Os clientes enviam um payload JSON contendo a consulta, o orçamento de tokens e o número máximo de tentativas ruins permitidas.
  • O servidor cria um novo rastreador (para uso de tokens e estado da ação) e atribui um requestId exclusivo.
  • A solicitação é processada assíncronamente chamando getResponse.
  • Uma vez concluída, a resposta final é armazenada e o progresso é emitido usando um EventEmitter.

Endpoint de Streaming (GET /api/v1/stream/:requestId):

  • Este endpoint utiliza Server-Sent Events (SSE) para enviar continuamente atualizações de volta ao cliente.
  • À medida que o agente executa ações (buscar, refletir, visitar, responder), eventos de progresso são emitidos. Cada evento inclui informações sobre o passo atual, uso de tokens e detalhes da ação.
  • Isso permite que os clientes monitorem o processo de pesquisa em tempo real.

Armazenamento e Recuperação de Tarefas:

O servidor grava os resultados das tarefas no sistema de arquivos (em um diretório tasks) e fornece um endpoint (GET /api/v1/task/:requestId) para recuperar um resultado armazenado.

Este componente do servidor web torna o agente de pesquisa acessível via HTTP, permitindo tanto experimentos interativos quanto integração em sistemas maiores.


2.4 test-duck.ts – Uma Utilidade para Testar Busca

O arquivo test-duck.ts é um script autônomo que usa Axios para enviar uma solicitação HTTP GET a uma API externa (neste caso, jsonplaceholder.typicode.com) como um teste. Embora sua função principal seja verificar se as solicitações HTTP funcionam corretamente (incluindo a definição de cabeçalhos adequados e o tratamento de erros), ele serve como um exemplo de como as solicitações externas são tratadas dentro do sistema. Em uma configuração mais complexa, padrões semelhantes são utilizados ao consultar APIs de busca, como DuckDuckGo ou Brave.


2.5 types.ts – Definindo Estruturas de Dados Consistentes

O arquivo types.ts define todos os tipos personalizados usados ao longo do projeto:

Tipos de Ação:
Estes incluem as várias ações que o agente pode realizar:

  • SearchAction: Contém uma string searchQuery.
  • AnswerAction: Requer uma string answer e references de apoio.
  • ReflectAction: Inclui um array de questionsToAnswer.
  • VisitAction: Contém uma lista de URLTargets.

Tipos de Resposta:
O arquivo define respostas estruturadas para resultados de busca, leitura de URLs, avaliação, análise de erros e mais. Isso ajuda a manter a consistência e assegura que cada módulo interprete os dados da mesma forma.

Tipos de Schema:
As definições do schema JSON garantem que as respostas geradas pelo modelo de linguagem atendam estritamente ao formato esperado. Isso é crucial para o processamento posterior.

Contexto do Rastreado:
Tipos personalizados para os rastreadores de tokens e ação também são definidos, que são usados para monitorar o estado da conversa e o processo de pesquisa.


3. O Processo Iterativo de Pesquisa Profunda

O sistema como um todo segue um processo metódico e iterativo que imita como um pesquisador humano poderia trabalhar:

Inicialização:
O processo começa com a pergunta original, que é adicionada a uma lista de "lacunas" (ou seja, os desconhecidos que precisam ser preenchidos).

Geração de Prompt:
O agente constrói um prompt usando a pergunta atual, o contexto anterior, o conhecimento coletado e até tentativas não-sucedidas. Este prompt é então enviado ao modelo de IA generativa.

Seleção de Ação:
Com base na saída do modelo, o agente seleciona uma entre várias ações:

  • Buscar: Formular uma nova consulta para coletar mais dados.
  • Visitar: Recuperar conteúdo detalhado de uma URL específica.
  • Refletir: Gerar sub-perguntas esclarecedoras para abordar quaisquer lacunas de conhecimento.
  • Responder: Fornecer uma resposta final se a informação for considerada definitiva.

Atualização de Contexto:
Cada passo atualiza os rastreadores internos (uso de tokens e estado da ação) e arquiva o estado atual em arquivos. Isso assegura transparência e permite depurações ou revisões posteriores.

Avaliação e Looping:
Quando uma resposta é proposta, um passo de avaliação verifica se ela é definitiva. Se não for, o sistema armazena os detalhes da tentativa falha e ajusta sua estratégia. O ciclo continua até que uma resposta satisfatória seja encontrada ou até que o orçamento de tokens se esgote.

Modo Fera:
Se os passos normais não conseguirem gerar uma resposta definitiva dentro das restrições, o sistema entra no "Modo Fera." Neste modo, a IA generativa é forçada a produzir uma resposta com base no contexto acumulado—mesmo que isso signifique fazer uma suposição educada.


4. Progresso e Feedback em Tempo Real

Um recurso integral do sistema DeepResearch é seu mecanismo de feedback em tempo real. Através do endpoint de streaming do servidor web:

  • Os clientes recebem atualizações de progresso que detalham qual ação foi tomada, estatísticas de uso de tokens e o estado atual do rastreador de ações.
  • Os eventos de progresso (como mostrado nos exemplos do README) incluem tanto o processo de pensamento do agente quanto detalhes como o passo atual e a quebra de tokens.
  • Este loop de feedback ao vivo é inestimável para depuração, monitoramento do uso de recursos e compreensão de como o sistema está raciocinando.

Por exemplo, um evento de progresso pode parecer assim:

data: {
  "type": "progress",
  "trackers": {
    "tokenUsage": 74950,
    "tokenBreakdown": {
      "agent": 64631,
      "read": 10319
    },
    "actionState": {
      "action": "search",
      "thoughts": "O texto menciona vários investidores na Jina AI, mas não especifica porcentagens de propriedade. Uma busca direta é necessária.",
      "URLTargets": [],
      "answer": "",
      "questionsToAnswer": [],
      "references": [],
      "searchQuery": "Porcentagens de propriedade de investidores da Jina AI"
    },
    "step": 7,
    "badAttempts": 0,
    "gaps": []
  }
}

Esse relatório de progresso detalhado permite que os desenvolvedores vejam como o raciocínio do agente evolui ao longo do tempo, proporcionando insights sobre sucessos e áreas que precisam de melhoria.


5. Expandindo e Personalizando o DeepResearch

A natureza de código aberto deste projeto significa que você pode adaptar o sistema para suas necessidades. Aqui estão algumas ideias para expandir o DeepResearch:

Provedores de Busca Personalizados:
Você pode integrar provedores de busca adicionais ou personalizar o processo de reescrita de consultas para buscas específicas de domínio.

Módulos de Leitura Aprimorados:
Se você precisar de processamento de texto mais detalhado, pode integrar modelos de NLP alternativos ou ajustar o componente Jina Reader para lidar com novos tipos de conteúdo.

Avaliação Aprimorada:
O módulo avaliador atualmente verifica se uma resposta é definitiva. Você poderia expandir isso para incorporar métricas mais nuançadas, como análise de sentimento ou algoritmos de verificação de fatos.

Interface do Usuário:
Embora o sistema atual utilize uma interface de linha de comando e um servidor web simples para eventos de streaming, você poderia construir uma interface web ou mobile completa para sessões de pesquisa interativas.

Aprimoramentos de Escalabilidade:
A implementação atual funciona como um serviço de nó único. Para uso em produção, considere containerizar a aplicação e implantá-la usando Kubernetes ou outra plataforma de orquestração para gerenciar alto tráfego e processamento distribuído.


6. Segurança, Desempenho e Melhores Práticas

Ao implantar um sistema guiado por IA como o DeepResearch, existem algumas considerações adicionais:

Gerenciamento de Chaves de API:
Assegure-se de que suas chaves de API (para Gemini, Jina e Brave) sejam armazenadas de forma segura e nunca codificadas diretamente no seu código fonte. Variáveis de ambiente e cofres seguros são recomendados.

Limitação de Taxa:
A função sleep embutida ajuda a evitar limitações de taxa ao atrasar solicitações sucessivas. No entanto, considere implementar mecanismos de limitação de taxa adicionais no servidor ou nível da API gateway.

Validação de Dados:
Valide rigorosamente as consultas e respostas de entrada. O schema JSON definido no agente ajuda, mas você também deve validar as solicitações HTTP de entrada para prevenir entradas maliciosas.

Tratamento de Erros:
Um tratamento de erros robusto (como visto no código do servidor e no test-duck.ts) é crítico. Isso garante que falhas inesperadas da API ou respostas malformadas não travem o sistema.

Monitoramento de Recursos:
Rastrear o uso de tokens é essencial. As classes TokenTracker e ActionTracker fornecem insights sobre o consumo de recursos. Monitorar essas métricas pode ajudar na otimização do desempenho do sistema e na prevenção de uso excessivo.


7. Conclusão

O projeto DeepResearch da Jina AI exemplifica como processos de pesquisa complexos e iterativos podem ser construídos usando ferramentas de código aberto. Ao integrar motores de busca, modelos de IA generativa e loops de raciocínio inteligentes, o sistema refinamos continuamente sua resposta até ter certeza—ou até que os limites de recursos sejam alcançados.

Neste artigo, exploramos como recriar a Pesquisa Profunda da OpenAI usando uma abordagem de código aberto:

  • Discutimos os passos de instalação e a configuração do ambiente.
  • Detrinhamos os módulos centrais, desde a lógica do agente iterativo em agent.ts até a configuração, API do servidor web e definições de tipo.
  • Avaliamos o mecanismo de feedback em tempo real que transmite atualizações de progresso, proporcionando transparência no processo de raciocínio.
  • Finalmente, analisamos potenciais extensões, opções de personalização e melhores práticas para implantar tal sistema.

Ao tornar essas técnicas avançadas de pesquisa disponíveis como código aberto, projetos como o DeepResearch democratizam o acesso a métodos de IA de ponta. Seja você um pesquisador, desenvolvedor ou empresa que busca integrar capacidades de pesquisa profunda em seus fluxos de trabalho, este projeto serve tanto como inspiração quanto como uma base prática para construir sua própria solução.

O design iterativo—combinando busca, leitura, reflexão e resposta em um loop contínuo—garante que até mesmo consultas ambíguas ou complexas sejam tratadas com múltiplas camadas de escrutínio. E com uma arquitetura detalhada que rastreia o uso de tokens e fornece feedback ao vivo, você ganha profundos insights sobre o processo de raciocínio por trás de cada resposta.

Se você está ansioso para experimentar, clone o repositório, configure seu ambiente conforme descrito e execute consultas que variam de aritmética simples a questões de pesquisa multifacetadas. Com um pouco de personalização, você pode adaptar o sistema a novos domínios e até mesmo aprimorar suas capacidades de raciocínio. Projetos de código aberto como este abrem caminho para inovações impulsionadas pela comunidade na pesquisa de IA.


Seguindo esta análise e detalhamento, você pode recriar e expandir as ideias por trás da Pesquisa Profunda da OpenAI de uma maneira totalmente de código aberto. Se você está procurando expandir a base de código existente ou integrar metodologias semelhantes em seus projetos, o caminho está claro: iterar, refinar e expandir os limites da pesquisa automatizada.

botão