03-02-02 — ReAct, self-consistency e tree-of-thought
TL;DR
ReAct combina raciocínio com ação — é a base intelectual de qualquer agente LLM. Self-consistency gera múltiplas respostas e vota na melhor — aumenta confiabilidade a custo de mais tokens. Tree-of-Thought explora múltiplos caminhos de raciocínio em paralelo. Cada técnica tem seu contexto ideal: ReAct para agentes, self-consistency para decisões críticas, ToT para problemas de busca complexos.
ReAct: Reason + Act
ReAct (Reasoning + Acting) é um padrão de prompting que intercala pensamento e ação. O modelo alterna entre:
- Thought: o que preciso fazer agora?
- Action: executa uma ferramenta (busca, cálculo, API)
- Observation: o resultado da ação
- ...repete até chegar na resposta final
É o loop fundamental de qualquer agente LLM. Frameworks como LangChain, AutoGen e Semantic Kernel implementam ReAct por baixo dos panos.
from openai import OpenAI
import json
client = OpenAI()
# Simulação do loop ReAct (versão simplificada sem framework)
def search_tool(query: str) -> str:
"""Simula uma busca no sistema interno."""
# Na vida real: chama sua API, banco de dados, etc.
if "SLA" in query:
return "SLA crítico: 4h. SLA alta: 8h. SLA média: 24h."
return "Informação não encontrada."
def calculator_tool(expression: str) -> str:
"""Executa cálculo simples."""
try:
return str(eval(expression))
except:
return "Erro no cálculo."
# System prompt ReAct
REACT_SYSTEM = """Você resolve problemas usando raciocínio e ferramentas.
Para cada passo, use o formato:
Thought: [seu raciocínio]
Action: [nome_da_ferramenta]
Action Input: [input para a ferramenta]
Observation: [resultado — será preenchido pelo sistema]
... (repita quantas vezes precisar)
Final Answer: [resposta final]
Ferramentas disponíveis: search, calculator"""
messages = [
{"role": "system", "content": REACT_SYSTEM},
{"role": "user", "content": "Um incidente crítico foi aberto às 10h. Qual é o prazo máximo de resolução e a que horas isso é?"}
]
# Loop ReAct simplificado
for iteration in range(5):
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
stop=["Observation:"] # para antes de inventar a observação
)
reply = response.choices[0].message.content
messages.append({"role": "assistant", "content": reply})
if "Final Answer:" in reply:
print("Resposta final:", reply.split("Final Answer:")[-1].strip())
break
# Extrai e executa a ação
if "Action: search" in reply:
action_input = reply.split("Action Input:")[-1].strip()
result = search_tool(action_input)
messages.append({"role": "user", "content": f"Observation: {result}"})
elif "Action: calculator" in reply:
action_input = reply.split("Action Input:")[-1].strip()
result = calculator_tool(action_input)
messages.append({"role": "user", "content": f"Observation: {result}"})
Self-consistency: vote na melhor resposta
Gera N respostas independentes para a mesma pergunta com temperatura > 0 e escolhe a resposta mais comum (por votação ou por um LLM juiz). Funciona porque aumenta a chance de chegar na resposta correta.
from collections import Counter
def self_consistency(question: str, n: int = 5, model: str = "gpt-4o") -> str:
"""Gera N respostas e retorna a mais frequente."""
responses = []
for i in range(n):
response = client.chat.completions.create(
model=model,
messages=[
{"role": "system", "content": "Raciocine passo a passo e conclua com 'Resposta: [sua resposta]'"},
{"role": "user", "content": question}
],
temperature=0.7 # variabilidade intencional
)
text = response.choices[0].message.content
# Extrai só a resposta final
if "Resposta:" in text:
answer = text.split("Resposta:")[-1].strip().split("\n")[0]
responses.append(answer)
# Votação: retorna a resposta mais comum
if responses:
vote = Counter(responses).most_common(1)[0]
print(f"Resposta vencedora: '{vote[0]}' ({vote[1]}/{n} votos)")
return vote[0]
return ""
# Exemplo: decisão que pode ter variabilidade
resultado = self_consistency(
"Dado que nosso sistema processa 10.000 transações/dia e crescemos 20% ao mês, em quantos meses atingimos 50.000 transações/dia?",
n=5
)
Tree-of-Thought (ToT)
ToT explora múltiplos caminhos de raciocínio em uma estrutura de árvore. O modelo gera "ramos" de pensamento, avalia cada um, e continua pelos mais promissores. É útil para problemas de planejamento, puzzles, ou quando a solução requer exploração de alternativas.
# Tree-of-Thought simplificado: gera, avalia, refina
def tree_of_thought(problem: str, branches: int = 3, depth: int = 2) -> str:
"""
Implementação simplificada de ToT:
1. Gera N abordagens iniciais
2. Avalia cada uma
3. Aprofunda as melhores
"""
# Passo 1: gera abordagens
step1 = client.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "user",
"content": f"""Problema: {problem}
Gere {branches} abordagens diferentes para resolver este problema.
Para cada abordagem, escreva apenas 2-3 linhas descrevendo a estratégia.
Formato: Abordagem 1: ... | Abordagem 2: ... | Abordagem 3: ..."""
}
]
)
approaches = step1.choices[0].message.content
# Passo 2: avalia qual abordagem é mais promissora
step2 = client.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "user",
"content": f"""Problema: {problem}
Abordagens geradas:
{approaches}
Qual abordagem tem maior chance de sucesso? Explique por que e desenvolva essa abordagem completamente."""
}
]
)
return step2.choices[0].message.content
# Exemplo prático
resultado = tree_of_thought(
"Nossa empresa precisa reduzir o tempo de onboarding de novos desenvolvedores de 4 semanas para 1 semana sem reduzir qualidade."
)
print(resultado)
Quando usar cada técnica
| Técnica | Ideal para | Custo relativo | Latência |
|---|---|---|---|
| ReAct | Agentes com acesso a ferramentas, tarefas multi-step com dados externos | Médio-alto (múltiplas chamadas) | Alta (espera por tools) |
| Self-consistency | Decisões críticas onde precisão > custo, cálculos com raciocínio | Alto (N × custo base) | Alta (N chamadas paralelas) |
| Tree-of-Thought | Planejamento estratégico, problemas com múltiplas soluções válidas | Alto (exploração de caminhos) | Muito alta |
| CoT simples | Maioria das tarefas de raciocínio | Baixo (+20% tokens) | Baixa |
Como isso se conecta
- → 03-02-01 CoT: ReAct é CoT com a extensão de poder agir — se você não entendeu CoT, volte um tópico
- → Módulo 05 (Agentes): ReAct é o coração de todo agente LLM — você vai implementar isso com Semantic Kernel e LangGraph
- → 03-02-03 Structured outputs: no loop ReAct, a "Action" precisa ser parseable — structured outputs garantem que o modelo retorne JSON válido
Fontes
- ReAct: Synergizing Reasoning and Acting in Language Models — Yao et al., 2022 (arXiv:2210.03629)
- Self-Consistency Improves Chain of Thought Reasoning — Wang et al., 2022 (arXiv:2203.11171)
- Tree of Thoughts: Deliberate Problem Solving with Large Language Models — Yao et al., 2023 (arXiv:2305.10601)
- Microsoft Learn — Semantic Kernel Agents