Como Desenvolver um Fluxo de Trabalho Agente de Pesquisa Profunda com LangChain e a API de LLM da Novita AI

Como Desenvolver um Fluxo de Trabalho Agente de Pesquisa Profunda com LangChain e a API de LLM da Novita AI

Várias empresas de IA estão agora introduzindo sistemas de IA agentes que podem realizar pesquisas profundas sobre o tópico solicitado e produzir um relatório abrangente, como o Deep Research da OpenAI.

Sistemas de IA agentes como o Deep Research da OpenAI oferecem pipelines automatizados para tarefas complexas, como busca em múltiplas etapas e síntese. Mas a maioria das soluções existentes são de código fechado, difíceis de personalizar e limitam seu controle sobre o comportamento do modelo e o tratamento dos dados.

Por exemplo, você pode querer usar um LLM diferente, um provedor de busca personalizado ou ajustar como os agentes planejam e se comportam para produzir saídas específicas.

Isso nos leva a uma pergunta interessante: você pode criar seu próprio agente de pesquisa profunda com total flexibilidade, onde pode usar seu modelo de IA preferido, integrar seu mecanismo de busca preferido e personalizar como o agente se comporta? A resposta é sim.

Neste artigo, você aprenderá como construir seu próprio agente de pesquisa profunda usando Novita AI, LangChain e Tavily.

O que é um Fluxo de Trabalho Agente de Pesquisa Profunda?

A pesquisa tradicional muitas vezes consome tempo, pois geralmente envolve vasculhar muitas informações disponíveis online e, no final, pode não levar a insights. Um Fluxo de Trabalho Agente de Pesquisa Profunda resolve esses problemas por meio de agentes de IA que podem raciocinar autonomamente, tomar decisões e coordenar ferramentas externas como parte de um fluxo de trabalho.

Esse fluxo de trabalho geralmente envolve:

  1. Estruturação de Tarefas: O agente de IA divide o tópico em tarefas menores.

  2. Planejamento: O agente cria estratégias para abordar cada tarefa, o que ajuda o fluxo de trabalho a determinar a sequência de execução das tarefas.

  3. Integração de Ferramentas: Para coletar informações, o agente usa diferentes ferramentas, como bancos de dados e mecanismos de busca na web. Sem essas ferramentas, o agente não pode executar ações-chave no fluxo de trabalho.

  4. Síntese: O agente analisa as informações coletadas e as combina em dados coerentes.

  5. Geração de Relatório: Após sintetizar os dados, o agente cria um relatório estruturado que inclui resumos e citações.

Ferramentas que Você Vai Precisar

Antes de entrarmos na parte de construção deste artigo, vamos configurar as ferramentas necessárias.

Novita AI

Para construir o fluxo de trabalho agente, precisaremos de um LLM, e a Novita AI fornece uma API acessível e de alto desempenho que dá acesso aos LLMs mais recentes, modelos de geração de imagens e muito mais.

Faça login na Novita AI para começar. Após o login, navegue até Settings > Key Management e siga as instruções para gerar uma chave de API.

Observe que, se você se inscrever, a Novita AI fornecerá créditos gratuitos para testar vários modelos, então não se preocupe em comprar créditos antes de começar a construir ou experimentar.

Página de login da Novita AI

Tavily

Tavily é uma API de busca web avançada otimizada para aplicações de IA. Com a ferramenta de busca do Tavily, podemos dar ao nosso agente acesso à internet para ajudar a coletar informações precisas e imparciais. Acesse o Tavily e gere uma chave de API.

Página inicial do Tavily

Langchain

LangChain é um framework de código aberto projetado para construir aplicações com LLMs. Com LangChain, você pode criar um fluxo de trabalho agente que raciocina passo a passo, usa ferramentas e interage com APIs. Para nosso agente de pesquisa profunda, usaremos LangChain para estruturar o processo de pesquisa, usar ferramentas como busca web e sintetizar tudo em um relatório estruturado.

langchain

Google Colab

Neste tutorial, vamos construir e testar o Agente de Pesquisa Profunda usando Google Colab. Colab permite que você escreva e execute código Python no seu navegador sem necessidade de configuração; isso torna o tutorial simples de acompanhar.

Visão Geral do Fluxo de Trabalho

A busca agente profunda é uma combinação de diferentes etapas do fluxo de trabalho, desde o planejamento da tarefa de busca até a entrega do relatório final de pesquisa. Vamos passar por cada etapa do fluxo de trabalho para entender como a aplicação funciona.

fluxo de trabalho agente profundo

Planejamento da Pesquisa

Esta é a primeira etapa do fluxo de trabalho. Aqui, o agente analisa o tópico e cria um plano de pesquisa estruturado com base no contexto do tópico. Ele divide o assunto amplo em subtópicos direcionados como histórico, detalhes técnicos, prós e contras, casos de uso e mais.
Você pode considerar esta a parte mais importante do fluxo de trabalho, pois sem ela, o agente pode realizar buscas genéricas e retornar resultados irrelevantes.

Busca Aprofundada

Os LLMs são limitados aos seus dados de treinamento e não podem acessar tendências atuais. Por exemplo, se você solicitar ao agente sem capacidade de busca que liste os jogadores atuais de um time de futebol, ele retornará resultados com base nos dados com os quais foi treinado. No entanto, como esses resultados não contêm as atualizações mais recentes, eles podem não estar mais factualmente corretos.
O uso do Tavily para realizar buscas web avançadas dá ao agente acesso às fontes web mais recentes e relevantes.

Gerenciamento de Fontes

Para garantir que cada informação que o agente produz possa ser vinculada a uma fonte confiável, é importante manter o controle de todas as fontes. Esta parte do fluxo de trabalho constrói confiança com usuários que desejam verificar alegações ou dados no relatório final.

Síntese

Para conectar os pontos entre todas as informações coletadas, o agente reúne insights de todos os aspectos pesquisados para formar um relatório coerente. Sem esta fase do fluxo de trabalho, a saída da pesquisa pode ser apenas um relatório desconexo.

Formatação Final

Mesmo que o relatório seja factualmente preciso e bem pesquisado, uma formatação pobre pode dificultar a leitura. Uma etapa adicional é necessária para garantir uma estrutura limpa, cabeçalhos consistentes, marcadores, espaçamento e mais.

Implementando o Agente de Pesquisa Profunda

Até agora, você entendeu o que é o fluxo de trabalho agente de pesquisa profunda. Agora é hora de implementá-lo no Google Colab.

Para começar, realizaremos algumas etapas principais:

Passo 1: Instalar Dependências

 -q langchain langchain-openai tavily-python

Passo 2: Importar Bibliotecas Necessárias

# Importar bibliotecas Python padrão
import os   # Para interagir com variáveis de ambiente
import re   # Para expressões regulares
import ast  # Para analisar com segurança expressões Python a partir de strings

# Modelos e ferramentas LangChain
from langchain_openai import ChatOpenAI # Interface para interagir com modelos de chat da OpenAI

from langchain_community.utilities.tavily_search import TavilySearchAPIWrapper  # Permite busca via API Tavily

# Esquema de mensagens LangChain
from langchain.schema import SystemMessage, HumanMessage  # Define tipos de mensagem usados em conversas

# Componentes de agente LangChain
from langchain.agents import Tool, AgentExecutor, create_react_agent  # Para construir e executar fluxos de trabalho agentes com ferramentas

# Modelos de prompt LangChain
from langchain.prompts import PromptTemplate  # Permite criar modelos de prompt reutilizáveis

# Memória LangChain
from langchain.memory import ConversationBufferMemory  # Ajuda a manter o estado da conversa entre turnos

Passo 3: Configurar Variáveis de Ambiente

# Configurando e recuperando variáveis de ambiente
os.environ["NOVITA_API_KEY"] = ""      # Substitua pela sua chave real da Novita API
os.environ["TAVILY_API_KEY"] = ""      # Substitua pela sua chave real da Tavily API

# Carregar as chaves de API em variáveis
novita_api_key = os.getenv("NOVITA_API_KEY")
tavily_api_key = os.getenv("TAVILY_API_KEY")

Passo 4: Definir uma Função Auxiliar LLM

A Novita AI é compatível com OpenAI; portanto, usaremos o módulo ChatOpenAI do LangChain para integrar a Novita AI com LangChain. Isso significa que podemos nos comunicar com a Novita da mesma forma que faríamos com modelos da OpenAI.

No entanto, uma coisa importante a observar é que precisamos definir o base_url para apontar para o endpoint da API da Novita: https://api.novita.ai/v3/openai.

Neste fluxo de trabalho, usaremos o modelo llama-4-maverick-17b-128e-instruct-fp8, que é uma variante poderosa do LLaMA 4 ajustada para tarefas de seguir instruções.

# Função auxiliar LLM
def llm(api_key,
        model="meta-llama/llama-4-maverick-17b-128e-instruct-fp8",
        temperature=0.7):
    """Cria uma instância ChatOpenAI LLM com parâmetros específicos."""    
    return ChatOpenAI(
        model=model,
        openai_api_key=api_key,
        base_url="https://api.novita.ai/v3/openai",
        temperature=temperature,
    )

Construindo o Pesquisador Agente

Todo o fluxo de trabalho de pesquisa profunda é encapsulado em uma classe modular chamada AgenticResearcher. Esta classe gerenciará o processo de geração de planos de pesquisa, realização de buscas web, síntese de resultados, formatação do relatório final e execução do loop completo de pesquisa.

Inicializaremos o agente de pesquisa com acesso a um LLM via API da Novita e uma ferramenta de busca web via API do Tavily. Em seguida, definimos um método que realiza uma busca web avançada em uma determinada consulta usando Tavily. Os resultados são formatados para legibilidade, e os dados brutos são armazenados para uso posterior.

class AgenticResearcher:
    def __init__(self, novita_api_key, tavily_api_key, num_researchers=3, temperature=0.3):
        """Inicializa o agente de pesquisa com as chaves de API e parâmetros necessários."""
        self.llm = llm(api_key=novita_api_key, temperature=temperature)
        self.tavily_search = TavilySearchAPIWrapper(tavily_api_key=tavily_api_key)
        self.num_researchers = num_researchers
        self.raw_search_results = []

    def search(self, query):
        """Pesquisa na web informações sobre uma determinada consulta."""
        try:
            results = self.tavily_search.results(
                query, max_results=7,
                search_depth="advanced"
            )
            # Armazenar resultados brutos para processamento de citações
            self.raw_search_results.extend(results)
            formatted = []
            for r in results:
                formatted += [
                    f"TITLE: {r.get('title','')}",
                    f"URL: {r.get('url','')}",
                    f"CONTENT:\n{r.get('content','')}",
                    "---"
                ]
            return "\n".join(formatted) if formatted else "Nenhum resultado encontrado"
        except Exception as e:
            return f"Erro na busca: {str(e)}"

Criando Planos de Pesquisa com Múltiplos Aspectos

Ainda como parte da classe AgenticResearcher, vamos criar um método que gera um plano de pesquisa estruturado, dividindo o tópico em vários aspectos distintos usando o LLM. Cada aspecto inclui um título e uma consulta de pesquisa específica. O objetivo é explorar o tópico de múltiplos ângulos para garantir profundidade e amplitude.

    def create_research_plan(self, topic):
        """Cria um plano de pesquisa estruturado com múltiplos aspectos a investigar."""
        sys = "Você é um planejador que gera listas Python de dicionários."
        hum = f"""

Crie um plano de pesquisa abrangente para: {topic}
Identifique {self.num_researchers} aspectos distintos para investigar minuciosamente.
Analise o tópico e determine os aspectos mais relevantes a pesquisar com base em sua natureza e domínio.
Saída exatamente:
ASPECT {{'title': '...', 'search_query': '...'}}
"""
        try:
            resp = self.llm.invoke([SystemMessage(content=sys), HumanMessage(content=hum)])
            aspects = []
            for line in resp.content.splitlines():
                if line.strip().startswith("ASPECT"):
                    m = re.search(r"\{.*\}", line)
                    if m:
                        try:
                            aspects.append(ast.literal_eval(m.group(0)))
                        except Exception as e:
                            print(f"Erro ao analisar aspecto: {e}")
            if not aspects:
                # Aspectos padrão de uso geral que funcionam em diferentes domínios
                default_aspects = [
                    {"title": "Visão Geral e Informações Principais", "search_query": f"{topic} overview key facts"},
                    {"title": "Contexto e Histórico", "search_query": f"{topic} background history context"},
                    {"title": "Detalhes e Especificações", "search_query": f"{topic} details specifics data"},
                    {"title": "Análise e Significado", "search_query": f"{topic} analysis importance implications"}
                ]
                aspects = default_aspects[:self.num_researchers]
            return aspects
        except Exception as e:
            print(f"Erro ao criar plano de pesquisa: {e}")
            return [{"title": f"pesquisa {topic}", "search_query": topic}]

Gerenciamento de Fontes e Citação

Em seguida, precisamos lidar com a forma como o fluxo de trabalho gera relatórios confiáveis. Vamos fazer isso criando um método que extrai fontes únicas dos resultados de busca brutos, garantindo que cada fonte seja citada.

    def extract_sources(self):
        """Extrai fontes únicas dos resultados de busca brutos para citações."""
        unique_sources = {}
        for result in self.raw_search_results:
            url = result.get('url', '')
            if url and 'http' in url:
                domain = url.split('/')[2] if len(url.split('/')) > 2 else url
                if domain not in unique_sources:
                    unique_sources[domain] = url
        return unique_sources

Síntese do Relatório

Agora que coletamos informações brutas de múltiplas fontes, o próximo passo é transformar essa entrada bagunçada em um relatório de pesquisa detalhado. Vamos escrever métodos que sintetizam o texto bruto em um relatório legível e organizado, com cabeçalhos, subtítulos, principais descobertas e citações de fontes.

    def synthesize(self, text):
        """Sintetiza texto bruto em descobertas detalhadas e estruturadas com citações."""
        sources = self.extract_sources()
        sources_list = list(sources.keys())
        sys = """Você é um sintetizador de pesquisa especialista que cria relatórios detalhados e estruturados.
Para cada afirmação ou fato que incluir, adicione uma citação ao domínio da fonte.
Use exatamente os nomes de domínio fornecidos, sem modificação.
Adapte a estrutura do seu relatório ao domínio e à natureza do tópico."""
        hum = f"""
INFORMAÇÕES A SINTETIZAR:
{text}
DOMÍNIOS DE FONTE DISPONÍVEIS (use estes nomes exatos para as citações):
{sources_list}
Crie um relatório de pesquisa abrangente e detalhado com:
1. Principais descobertas com fatos e números específicos
2. Informações estruturadas com cabeçalhos e subtítulos claros e apropriados ao tópico
3. Citações usando exatamente os nomes dos domínios de fonte entre colchetes [assim.mesmo]
4. Dados relevantes apresentados de forma clara e profissional
5. Formato adaptado à natureza específica do tópico (técnico, histórico, evento noticioso, etc.)
FORMATE O RELATÓRIO DE FORMA PROFISSIONAL E COMPLETA, SEM ASSUMIR NENHUM DOMÍNIO ESPECÍFICO.
"""
        try:
            return self.llm.invoke([SystemMessage(content=sys), HumanMessage(content=hum)]).content
        except Exception as e:
            return f"Erro na síntese: {str(e)}"

Criando Ferramentas para o Agente

Para tornar nosso fluxo de trabalho agente de pesquisa profunda funcional, precisamos definir as ferramentas. As ferramentas dão ao agente capacidades para realizar certas ações.

As principais ferramentas necessárias para este fluxo de trabalho são: “plan” para ajudar o agente a dividir o tópico e criar um plano de pesquisa estruturado, “search” para permitir que o agente realize uma busca web profunda e “synthesize” para permitir que o agente converta todas as descobertas brutas em um relatório organizado.

    def get_tools(self):
        """Cria e retorna a lista de ferramentas disponíveis para o agente."""
        return [
            Tool(
                name="plan",
                func=lambda t: str(self.create_research_plan(t)),
                description="Cria um plano de pesquisa detalhado com múltiplos aspectos a investigar."
            ),
            Tool(
                name="search",
                func=self.search,
                description="Pesquisa na web minuciosamente por uma consulta e retorna resultados abrangentes."
            ),
            Tool(
                name="synthesize",
                func=self.synthesize,
                description="Transforma texto bruto em descobertas detalhadas e estruturadas com citações."
            ),
        ]

Construindo o Executor do Agente

Agora que nossas ferramentas estão prontas, precisamos unir tudo em um agente de IA usando um estilo de prompt ReAct. Isso ajuda o agente a planejar, realizar ações usando as ferramentas definidas, observar os resultados e repetir até que tenha dados suficientes para produzir um relatório de pesquisa final.

    def get_agent_executor(self):
        """Cria e retorna o executor do agente com ferramentas e memória."""
        tools = self.get_tools()
        template = """Você é um agente de pesquisa autônomo especializado em produzir relatórios abrangentes e detalhados sobre qualquer tópico.
{tool_names}
FERRAMENTAS:
{tools}
CONVERSAS ANTERIORES:
{chat_history}
Quando receber um tópico de pesquisa (como {input}), siga este processo:
1. Analise o tipo de tópico e crie um plano de pesquisa adaptado ao seu domínio
2. Pesquise informações abrangentes sobre cada aspecto do tópico
3. Colete informações detalhadas e relevantes com fontes
4. Sintetize tudo em um relatório profissional e detalhado, formatado adequadamente para o tópico
Siga exatamente este formato:
Pergunta: {input}
Thought: (seu raciocínio aqui)
Action: o nome da ferramenta a ser chamada, deve ser um de [{tool_names}]
Action Input: a entrada para a ferramenta
Observation: (a saída da ferramenta)
... (repita Thought/Action/Action Input/Observation conforme necessário)
Quando tiver coletado informações abrangentes, produza:
Final Answer: (seu relatório de pesquisa final e detalhado, com seções estruturadas, formatação adequada, detalhes específicos e citações)
COMEÇE COM UM PLANO ABRANGENTE!
{agent_scratchpad}
"""
        prompt = PromptTemplate(
            template=template,
            input_variables=["input", "agent_scratchpad", "tools", "tool_names", "chat_history"]
        )

        # Criar o agente de baixo nível
        agent = create_react_agent(
            llm=self.llm,
            tools=tools,
            prompt=prompt
        )

        # Envolver em um executor com memória
        memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
        agent_executor = AgentExecutor.from_agent_and_tools(
            agent=agent,
            tools=tools,
            verbose=True,
            memory=memory,
            max_iterations=18,
            early_stopping_method="generate",
            handle_parsing_errors=True
        )
        return agent_executor

Formatação Final do Relatório

Após o agente de pesquisa concluir sua busca profunda, a saída pode ser informativa, mas não apresentável. Esta etapa adicional ajuda a tornar o relatório final mais polido. Para conseguir isso, vamos solicitar ao LLM que atue como um editor especialista para melhorar o relatório final.

    def format_final_report(self, raw_report):
        """Adiciona formatação final ao relatório para torná-lo mais profissional."""
        sys = """Você é um editor especialista que melhora relatórios de pesquisa.
Mantenha todo o conteúdo factual, citações e estrutura intactos.
Apenas melhore a formatação, organização e legibilidade."""
        hum = f"""
Aqui está um relatório de pesquisa que precisa de melhorias finais de formatação:
{raw_report}
Por favor, melhore a formatação e apresentação, preservando tudo:
1. Fatos e números
2. Citações
3. Organização do conteúdo
4. Dados estatísticos
Faça com que pareça profissional, com cabeçalhos adequados, espaçamento e layout.
"""
        try:
            improved = self.llm.invoke([SystemMessage(content=sys), HumanMessage(content=hum)]).content
            return improved
        except Exception as e:
            # Se a formatação falhar, retornar o relatório original
            return raw_report

Juntando Tudo

Vamos unir todo o fluxo de trabalho em um pipeline que coordena todo o processo de pesquisa. Isso servirá como ponto de entrada que permite ao agente realizar o processo completo de pesquisa e depois formatar o relatório final.

    def run(self, topic):
        """Executa o processo de pesquisa sobre o tópico fornecido."""
        try:
            # Reiniciar resultados de busca armazenados
            self.raw_search_results = []

            # Executar o agente
            executor = self.get_agent_executor()
            raw_report = executor.invoke({"input": topic})["output"]

            # Formatar o relatório final
            final_report = self.format_final_report(raw_report)
            return final_report
        except Exception as e:
            return f"Pesquisa falhou: {str(e)}"

Executando o Agente de Pesquisa

Agora que construímos o fluxo de trabalho agente de pesquisa profunda, vamos testá-lo para ver como ele se sai em uma tarefa de pesquisa real.

Vamos criar uma instância do agente de pesquisa e pedir que ele gere um relatório detalhado sobre um tópico atual.

# Criar o objeto pesquisador
researcher = AgenticResearcher(novita_api_key, tavily_api_key, num_researchers=3)

# Executar uma pesquisa de teste
topic = "Quais são as startups de tecnologia climática mais promissoras em 2025?"
report = researcher.run(topic)

# Exibir o relatório de pesquisa
print("\n" + "="*60)
print(f"📝 RELATÓRIO DE PESQUISA DETALHADO: {topic}")
print("="*60)
print(report)
print("="*60 + "\n")

Resultado:

O fluxo de trabalho agente profundo dividiu o tópico e criou um plano de pesquisa, realizou uma busca na internet para recuperar informações relevantes, sintetizou os dados coletados e finalmente retornou um relatório estruturado com base na consulta de pesquisa.

Conclusão

Parabéns por construir seu próprio fluxo de trabalho agente de pesquisa profunda! Agora você pode pesquisar qualquer tópico e obter um relatório detalhado sobre sua consulta.

Vamos fazer um breve resumo do que você realizou:

Neste artigo, você aprendeu como construir um agente de pesquisa profunda que pode dividir tópicos complexos, gerar um plano de pesquisa, realizar buscas na internet e sintetizar todas as descobertas em um relatório estruturado.

Todo este fluxo de trabalho foi alimentado por:

  • Novita AI como provedor de LLM
  • LangChain para o framework agente
  • Tavily como mecanismo de busca em tempo real

Sinta-se à vontade para testar o agente em diferentes tópicos para verificar suas capacidades!

Esta é apenas uma das muitas aplicações interessantes de IA possíveis com os modelos poderosos de hoje. Visite o Novita LLM Playground para testar outros modelos de IA de ponta; quem sabe, sua próxima grande ideia de IA pode começar a partir daí.

Confira o Código no Colab

Novita AI é uma plataforma de nuvem de IA que oferece aos desenvolvedores uma maneira fácil de implantar modelos de IA usando nossa API simples, além de fornecer GPUs na nuvem acessíveis e confiáveis para construir e escalar.