Como criar ReAct agents usando LlamaIndex
Agentes ReAct são uma das abordagens mais versáteis para criar assistentes de IA capazes de raciocinar e agir de forma autônoma. Neste guia, vamos explorar como construir um agente ReAct usando LlamaIndex, começando com ferramentas simples de calculadora para entender os conceitos fundamentais.
O que é um ReAct agent?
ReAct (Reasoning and Acting) é um paradigma que combina raciocínio e ação em agentes de linguagem. A principal vantagem do ReAct agent sobre um Function Calling agent é sua compatibilidade universal: ele funciona com qualquer Large Language Model (LLM), independentemente de suportar chamadas de função nativamente.
Configurando o ambiente
Antes de começar, instale o LlamaIndex:
%pip install llama-index
Configure sua chave da OpenAI:
import os
os.environ["OPENAI_API_KEY"] = "sk-..."
Definindo ferramentas funcionais
O primeiro passo é criar ferramentas que o agente poderá utilizar. Vamos começar com duas funções matemáticas básicas:
def multiply(a: int, b: int) -> int:
"""Multiply two integers and returns the result integer"""
return a * b
def add(a: int, b: int) -> int:
"""Add two integers and returns the result integer"""
return a + b
Note que as docstrings são importantes - o LlamaIndex as utiliza para que o agente entenda quando e como usar cada ferramenta.
Criando o ReAct agent
Com as ferramentas definidas, podemos instanciar nosso agente:
from llama_index.llms.openai import OpenAI
from llama_index.core.agent.workflow import ReActAgent
from llama_index.core.workflow import Context
llm = OpenAI(model="gpt-4o-mini")
agent = ReActAgent(tools=[multiply, add], llm=llm)
# Crie um contexto para armazenar o histórico de conversação
ctx = Context(agent)
Executando consultas
Vamos testar o agente com uma operação matemática simples:
from llama_index.core.agent.workflow import AgentStream, ToolCallResult
handler = agent.run("What is 20+(2*4)?", ctx=ctx)
async for ev in handler.stream_events():
if isinstance(ev, AgentStream):
print(f"{ev.delta}", end="", flush=True)
response = await handler
Observando o raciocínio do agente
O output mostra o processo de pensamento completo:
Thought: The current language of the user is: English. I need to use a tool to help me answer the question.
Action: multiply
Action Input: {"a": 2, "b": 4}
Thought: Now I have the result of the multiplication, which is 8. I will add this to 20 to complete the calculation.
Action: add
Action Input: {'a': 20, 'b': 8}
Thought: I can answer without using any more tools. I'll use the user's language to answer.
Answer: The result of 20 + (2 * 4) is 28.
Analisando as chamadas de ferramenta
Você pode inspecionar todas as chamadas de ferramenta realizadas:
print(response.tool_calls)
Isso retorna uma lista detalhada com:
Nome da ferramenta utilizada
Parâmetros passados
Output retornado
ID da chamada
Entendendo o prompt do sistema
O ReAct agent utiliza um prompt estruturado que define seu comportamento. Você pode visualizá-lo:
prompt_dict = agent.get_prompts()
for k, v in prompt_dict.items():
print(f"Prompt: {k}\n\nValue: {v.template}")
O prompt instrui o agente a:
Pensar antes de agir
Usar ferramentas em sequência apropriada
Seguir formato específico de output
Responder no idioma do usuário
Personalizando o prompt
Uma das funcionalidades mais poderosas é a capacidade de customizar o comportamento do agente através do prompt:
from llama_index.core import PromptTemplate
react_system_header_str = """
You are designed to help with a variety of tasks, from answering questions
to providing summaries to other types of analyses.
## Tools
You have access to a wide variety of tools. You are responsible for using
the tools in any sequence you deem appropriate to complete the task at hand.
## Output Format
[...formato específico...]
## Additional Rules
- The answer MUST contain a sequence of bullet points that explain how you arrived at the answer.
- You MUST obey the function signature of each tool.
"""
react_system_prompt = PromptTemplate(react_system_header_str)
agent.update_prompts({"react_header": react_system_prompt})
Testando com prompt customizado
Após customizar o prompt, o agente passa a seguir as novas regras:
handler = agent.run("What is 5+3+2")
async for ev in handler.stream_events():
if isinstance(ev, AgentStream):
print(f"{ev.delta}", end="", flush=True)
response = await handler
Casos de uso práticos
Embora este exemplo use ferramentas simples de calculadora, o padrão ReAct pode ser aplicado a cenários mais complexos:
Caso de Uso | Ferramentas Possíveis |
|---|---|
RAG Avançado | Busca vetorial, reranking, sumarização |
Análise de Dados | Consultas SQL, processamento de CSV, visualização |
Automação | APIs externas, web scraping, file operations |
Pesquisa | Search engines, knowledge bases, documentação |
Vantagens do ReAct agent
Compatibilidade universal: funciona com qualquer LLM
Raciocínio explícito: você pode ver o processo de pensamento
Flexibilidade: fácil adicionar novas ferramentas
Customização: controle total sobre o comportamento via prompts
Próximos passos
Agora que você entende os fundamentos do ReAct agent, experimente:
Adicionar ferramentas mais complexas
Integrar com pipelines RAG
Implementar multi-agent workflows
Customizar prompts para domínios específicos
O ReAct agent é uma ferramenta poderosa no arsenal de desenvolvimento com LlamaIndex. Sua simplicidade e versatilidade o tornam ideal tanto para prototipagem rápida quanto para sistemas de produção robustos.
FAQ
P: Qual a diferença entre ReAct e Function Calling agents?
R: ReAct agents funcionam com qualquer LLM, enquanto Function Calling agents requerem modelos com suporte nativo a chamadas de função.
P: Como adicionar mais ferramentas ao agente?
R: Basta passar uma lista de funções ao criar o ReActAgent: agent = ReActAgent(tools=[tool1, tool2, tool3], llm=llm)
P: É possível usar o agente em português?
R: Sim, o agente detecta automaticamente o idioma do usuário e responde no mesmo idioma.
P: Como fazer streaming apenas da resposta final?
R: Você pode filtrar os eventos e começar o streaming apenas quando "Answer:" aparecer no response.
