mirror of
https://github.com/langchain-ai/langgraph-reflection.git
synced 2026-07-01 16:00:21 -04:00
cr
This commit is contained in:
+10
@@ -0,0 +1,10 @@
|
||||
# Python-generated files
|
||||
__pycache__/
|
||||
*.py[oc]
|
||||
build/
|
||||
dist/
|
||||
wheels/
|
||||
*.egg-info
|
||||
|
||||
# Virtual environments
|
||||
.venv
|
||||
@@ -0,0 +1,36 @@
|
||||
# LangGraph-Reflexion
|
||||
|
||||
This prebuilt graph is an agent that uses a reflection-style architecture to check and improve an initial agent's output.
|
||||
|
||||
This reflection agent uses two subagents:
|
||||
- A "main" agent, which is the agent attempting to solve the users task
|
||||
- A "critique" agent, which checks the main agents work and offers any critiques
|
||||
|
||||
The reflection agent has the following architecture:
|
||||
|
||||
1. First, the main agent is called
|
||||
2. Once the main agent is finished, the critique agent is called
|
||||
3. Based on the result of the critique agent:
|
||||
- If the critique agent finds something to critique, then the main agent is called again
|
||||
- If there is nothing to critique, then the overall reflection agent finishes
|
||||
4. Repeat until the overall reflection agent finishes
|
||||
|
||||
|
||||
We make some assumptions about the graphs:
|
||||
- The main agent should take as input a list of messages
|
||||
- The reflection agent should return a **user** message if there is any critiques, otherwise it should return **no** messages.
|
||||
|
||||
## Examples
|
||||
|
||||
Below are a few examples of how to use this reflection agent.
|
||||
|
||||
### LLM-as-a-Judge
|
||||
|
||||
In this example, the reflection agent uses another LLM to judge it's output
|
||||
|
||||
|
||||
|
||||
### Coding
|
||||
|
||||
Code is easy to "check" in deterministic ways. In this example, we use a linter to check Python code.
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
from langgraph_reflexion import create_reflection_graph
|
||||
from langchain.chat_models import init_chat_model
|
||||
from langgraph.graph import StateGraph, MessagesState, START, END
|
||||
from typing import TypedDict
|
||||
|
||||
def call_model(state):
|
||||
return {"messages": init_chat_model(model="claude-3-7-sonnet-latest").invoke(state['messages'])}
|
||||
|
||||
graph = StateGraph(MessagesState).add_node(call_model).add_edge(START, "call_model").add_edge("call_model", END).compile()
|
||||
|
||||
|
||||
class Finish(TypedDict):
|
||||
finish: bool
|
||||
|
||||
|
||||
|
||||
critique_prompt = """Your job is to look at the conversation below, and look at the AI assistant's response.
|
||||
|
||||
Critique it. Make sure it is complete. Make sure it is well thoughtout. Make sure it does what the user wants.
|
||||
|
||||
If it is good, then call the `Finish` tool. If you don't call the `Finish` tool, your response will be sent back to the assistant, so make sure to include concrete feedback on how it can improve."""
|
||||
|
||||
def nl_critique(state, config):
|
||||
response = init_chat_model(model="o3-mini", model_provider="openai").bind_tools([Finish]).invoke(
|
||||
[{"role": "system", "content": critique_prompt}] + state['messages']
|
||||
)
|
||||
if len(response.tool_calls) == 1:
|
||||
return
|
||||
else:
|
||||
return {"messages": [{"role": "user", "content": response.content}]}
|
||||
|
||||
critique_graph_general = StateGraph(MessagesState).add_node(nl_critique).add_edge(START, "nl_critique").add_edge("nl_critique", END).compile()
|
||||
|
||||
overall_graph = create_reflection_graph(graph, critique_graph_general)
|
||||
@@ -0,0 +1,19 @@
|
||||
[project]
|
||||
name = "langgraph-reflexion"
|
||||
version = "0.0.1"
|
||||
description = "LangGraph agent that runs a reflection step"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = ["langgraph"]
|
||||
authors = [{name = "Harrison Chase"}]
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
where = ["src"]
|
||||
|
||||
[tool.uv.sources]
|
||||
langgraph-reflexion = { workspace = true }
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"langgraph-reflexion",
|
||||
]
|
||||
@@ -0,0 +1,30 @@
|
||||
from typing import Optional, Type, Any, Literal
|
||||
from langgraph.graph import END, START, StateGraph
|
||||
from langgraph.graph.state import CompiledStateGraph
|
||||
from langchain_core.messages import HumanMessage
|
||||
|
||||
|
||||
def end_or_reflect(state) -> Literal[END, "graph"]:
|
||||
if len(state["messages"]) == 0:
|
||||
return END
|
||||
last_message = state["messages"][-1]
|
||||
if isinstance(last_message, HumanMessage):
|
||||
return "graph"
|
||||
else:
|
||||
return END
|
||||
|
||||
|
||||
def create_reflection_graph(
|
||||
graph: CompiledStateGraph,
|
||||
reflection: CompiledStateGraph,
|
||||
state_schema: Optional[Type[Any]] = None,
|
||||
config_schema: Optional[Type[Any]] = None,
|
||||
) -> StateGraph:
|
||||
_state_schema = state_schema or graph.builder.schema
|
||||
rgraph = StateGraph(state_schema, config_schema=config_schema)
|
||||
rgraph.add_node("graph", graph)
|
||||
rgraph.add_node("reflection", reflection)
|
||||
rgraph.add_edge(START, "graph")
|
||||
rgraph.add_edge("graph", "reflection")
|
||||
rgraph.add_conditional_edges("reflection", end_or_reflect)
|
||||
return rgraph
|
||||
Reference in New Issue
Block a user