Padrão de Agente Reflexivo
Implemente o padrão de reflexão em LangGraph, loops de gerar, criticar e refinar para agentes que melhoram iterativamente sua saída.
O padrão de reflexão permite que os agentes se autoaprimorem gerando uma saída, criticando-a e refinando-a com base na crítica. Isso cria um ciclo de qualidade que produz resultados melhores do que a geração em uma única passagem.
O Loop de Reflexão
Generate → Critique → Refine → Critique → Refine → ... → Accept
Each iteration:
- Gerar: Produza a saída inicial (ou refine a anterior)
- Criticar: Analise a saída em busca de problemas, lacunas ou melhorias
- Refinar: Melhore com base na crítica
- Repetir: Até que o limite de qualidade seja atingido ou o número máximo de iterações seja alcançado
Grafo de Reflexão Básico
from langgraph.graph import StateGraph, START, END
from langchain_openai import ChatOpenAI
from typing_extensions import TypedDict
from typing import Annotated, List
from operator import add
llm = ChatOpenAI(model="gpt-4o")
class ReflectionState(TypedDict):
topic: str
drafts: Annotated[List[str], add] # Accumulate all drafts
critiques: Annotated[List[str], add] # Accumulate all critiques
final: str
iteration: int
max_iterations: int
def generate(state: ReflectionState) -> dict:
context = ""
if state["critiques"]:
# Incorporate last critique
last_critique = state["critiques"][-1]
context = f"\nPrevious critique to address:\n{last_critique}"
prompt = f"Write about: {state['topic']}. Be thorough and clear.{context}"
draft = llm.invoke(prompt).content
return {
"drafts": [draft],
"iteration": state["iteration"] + 1
}
def critique(state: ReflectionState) -> dict:
last_draft = state["drafts"][-1]
prompt = f"""Critique the following text. Identify:
1. Strengths
2. Weaknesses or gaps
3. Specific improvements needed
4. Clarity and structure issues
Text to critique:
{last_draft}
Be constructive and specific."""
critique_text = llm.invoke(prompt).content
return {"critiques": [critique_text]}
def should_continue(state: ReflectionState) -> str:
if state["iteration"] >= state["max_iterations"]:
return "finalize"
return "refine"
def finalize(state: ReflectionState) -> dict:
return {"final": state["drafts"][-1]}
# Build graph
builder = StateGraph(ReflectionState)
builder.add_node("generate", generate)
builder.add_node("critique", critique)
builder.add_node("finalize", finalize)
builder.add_edge(START, "generate")
builder.add_edge("generate", "critique")
builder.add_conditional_edges("critique", should_continue, {
"refine": "generate", # Loop back for another iteration
"finalize": "finalize"
})
builder.add_edge("finalize", END)
app = builder.compile()
# Run
result = app.invoke({
"topic": "Benefits of functional programming",
"drafts": [],
"critiques": [],
"final": "",
"iteration": 0,
"max_iterations": 3
})
print(result["final"])A crítica é alimentada de volta na próxima chamada de geração como contexto. O gerador aborda os pontos da crítica, criando um ciclo de melhoria contínua.
Crítica Estruturada com Pontuação
from pydantic import BaseModel, Field
class CritiqueScore(BaseModel):
clarity: float = Field(ge=0, le=10)
accuracy: float = Field(ge=0, le=10)
completeness: float = Field(ge=0, le=10)
conciseness: float = Field(ge=0, le=10)
overall: float = Field(ge=0, le=10)
issues: list[str]
suggestions: list[str]
def structured_critique(state: ReflectionState) -> dict:
from langchain_core.output_parsers import PydanticOutputParser
parser = PydanticOutputParser(pydantic_object=CritiqueScore)
prompt = ChatPromptTemplate.from_messages([
("system", "Critique the text and provide structured scores. {format_instructions}"),
("human", "{text}")
])
chain = prompt | llm | parser
score = chain.invoke({
"text": state["drafts"][-1],
"format_instructions": parser.get_format_instructions()
})
return {
"critiques": [f"Score: {score.overall}/10\nIssues: {', '.join(score.issues)}\nSuggestions: {', '.join(score.suggestions)}"]
}Críticas estruturadas com pontuações permitem acompanhar a melhoria ao longo das iterações e definir limites de qualidade para encerramento antecipado.
Término por Limiar de Qualidade
def quality_router(state: ReflectionState) -> str:
last_critique = state["critiques"][-1] if state["critiques"] else ""
# Check if quality is acceptable (simplified — look for score)
if "Score:" in last_critique:
try:
score_line = [l for l in last_critique.split("\n") if "Score:" in l][0]
score = float(score_line.split("/")[0].split(":")[1].strip())
if score >= 8.0: # Quality threshold met
return "finalize"
except (IndexError, ValueError):
pass
if state["iteration"] >= state["max_iterations"]:
return "finalize"
return "refine"Crítica de Múltiplas Perspectivas
Use múltiplos ângulos de crítica para um feedback completo:
def critic_expert(state: ReflectionState) -> dict:
"""Critique from an expert perspective."""
prompt = f"As a domain expert, critique this: {state['drafts'][-1]}"
return {"critiques": [f"[Expert] {llm.invoke(prompt).content}"]}
def critic_stylist(state: ReflectionState) -> dict:
"""Critique from a writing style perspective."""
prompt = f"As a writing stylist, critique the clarity and flow: {state['drafts'][-1]}"
return {"critiques": [f"[Style] {llm.invoke(prompt).content}"]}
def critic_fact_checker(state: ReflectionState) -> dict:
"""Critique from a factual accuracy perspective."""
prompt = f"Fact-check this text. Identify any unsupported claims: {state['drafts'][-1]}"
return {"critiques": [f"[Facts] {llm.invoke(prompt).content}"]}Múltiplos críticos fornecem perspectivas diferentes. O gerador recebe todas as críticas e deve abordá-las todas na próxima iteração.
Melhoria de Código com Reflexão
O padrão de reflexão também funciona para geração de código:
def generate_code(state: ReflectionState) -> dict:
context = ""
if state["critiques"]:
context = f"\nAddress these issues:\n{state['critiques'][-1]}"
prompt = f"Write Python code for: {state['topic']}. Include tests.{context}"
code = llm.invoke(prompt).content
return {"drafts": [code], "iteration": state["iteration"] + 1}
def critique_code(state: ReflectionState) -> dict:
code = state["drafts"][-1]
prompt = f"""Review this Python code for:
1. Correctness — will it work?
2. Edge cases — what could break it?
3. Performance — can it be optimized?
4. Style — does it follow PEP 8?
5. Security — are there vulnerabilities?
Code:
{code}
Be specific about each issue."""
critique_text = llm.invoke(prompt).content
return {"critiques": [critique_text]}Agente de Reflexão Completo
from langgraph.graph import StateGraph, START, END
from typing_extensions import TypedDict, Annotated
from typing import List
from operator import add
class AgentState(TypedDict):
task: str
outputs: Annotated[List[str], add]
feedback: Annotated[List[str], add]
iteration: int
max_iterations: int
def generate(state: AgentState) -> dict:
context = ""
if state["feedback"]:
context = f"\nPrevious feedback: {state['feedback'][-1]}"
prompt = f"Task: {state['task']}. Produce your best work.{context}"
return {"outputs": [llm.invoke(prompt).content], "iteration": state["iteration"] + 1}
def reflect(state: AgentState) -> dict:
prompt = f"Critique this output constructively:\n{state['outputs'][-1]}"
return {"feedback": [llm.invoke(prompt).content]}
def router(state: AgentState) -> str:
return "refine" if state["iteration"] < state["max_iterations"] else "done"
builder = StateGraph(AgentState)
builder.add_node("generate", generate)
builder.add_node("reflect", reflect)
builder.add_edge(START, "generate")
builder.add_edge("generate", "reflect")
builder.add_conditional_edges("reflect", router, {"refine": "generate", "done": END})
app = builder.compile()Perguntas de Prática (Practice Questions)
Como responder
Questão de múltipla escolha com 4 opções. Selecione uma opção e escolha Verificar resposta.
What is the reflection pattern in LangGraph?
Como responder
Questão de múltipla escolha com 4 opções. Selecione uma opção e escolha Verificar resposta.
How does the generate node use feedback from the critique node?
Como responder
Questão de múltipla escolha com 4 opções. Selecione uma opção e escolha Verificar resposta.
What determines when the reflection loop stops?
Como responder
Questão de múltipla escolha com 4 opções. Selecione uma opção e escolha Verificar resposta.
What is the advantage of structured critique with scores?
Como responder
Questão de múltipla escolha com 4 opções. Selecione uma opção e escolha Verificar resposta.
What is the benefit of multi-perspective critique?
Como responder
Questão de múltipla escolha com 4 opções. Selecione uma opção e escolha Verificar resposta.
How does the reflection pattern improve code generation?
Como responder
Questão de múltipla escolha com 4 opções. Selecione uma opção e escolha Verificar resposta.
What risk should you mitigate in the reflection loop?
Como responder
Questão de múltipla escolha com 4 opções. Selecione uma opção e escolha Verificar resposta.
What happens in the critique node of the basic reflection graph?
Como responder
Questão de múltipla escolha com 4 opções. Selecione uma opção e escolha Verificar resposta.
What does the 'add' reducer do for the drafts field in reflection state?
Como responder
Questão de múltipla escolha com 4 opções. Selecione uma opção e escolha Verificar resposta.
Can the reflection pattern be applied to agent decisions, not just text?
Principais Conclusões
- Padrão de reflexão: gerar → criticar → refinar: melhorando a saída de forma iterativa
- O feedback da crítica é passado como contexto para o próximo prompt de geração
- A pontuação estruturada permite acompanhamento quantitativo da qualidade e encerramento antecipado
- Críticas com múltiplas perspectivas capturam diferentes tipos de problemas
- O padrão funciona para texto, código e decisões de agentes
- Equilibre o número de iterações com o custo dos tokens
- O reducer 'add' preserva o histórico de melhorias
- Os limites de qualidade evitam iterações desnecessárias quando a saída já está boa