-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexample.py
More file actions
92 lines (76 loc) · 2.96 KB
/
Copy pathexample.py
File metadata and controls
92 lines (76 loc) · 2.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import os
from typing import TypedDict, Annotated, List
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.messages import BaseMessage, HumanMessage, AIMessage
from langgraph.graph import StateGraph, END
# Load environment variables (API keys)
load_dotenv()
# Define the state of our graph
class AgentState(TypedDict):
messages: Annotated[List[BaseMessage], lambda x, y: x + y]
iterations: int
# Initialize the model
llm = ChatOpenAI(model="gpt-4o", temperature=0.7)
def generator_node(state: AgentState):
"""Generates a response or an update based on feedback."""
response = llm.invoke(state['messages'])
return {
"messages": [response],
"iterations": state.get("iterations", 0) + 1
}
def critic_node(state: AgentState):
"""Critiques the generator's output to find potential improvements."""
# We take the last message (the generation) and ask for a critique
last_message = state['messages'][-1].content
critique_prompt = f"Critique the following code for efficiency, readability, and edge cases. Provide specific feedback for improvement:\n\n{last_message}"
critique = llm.invoke([HumanMessage(content=critique_prompt)])
# We mark this as a critique in the message history
return {"messages": [AIMessage(content=f"CRITIQUE: {critique.content}")]}
def should_continue(state: AgentState):
"""Decides whether to reflect again or finish."""
if state["iterations"] >= 2:
return END
return "critic"
# Define the Graph
workflow = StateGraph(AgentState)
# Add nodes
workflow.add_node("generator", generator_node)
workflow.add_node("critic", critic_node)
# Set entry point
workflow.set_entry_point("generator")
# Add edges
workflow.add_edge("critic", "generator")
workflow.add_conditional_edges(
"generator",
should_continue,
{
"critic": "critic",
END: END
}
)
# Compile
app = workflow.compile()
def visualize_graph():
"""Prints ASCII and saves PNG image using LangGraph's built-in method."""
print("\n--- Graph Visualization ---")
app.get_graph().print_ascii()
print("---------------------------\n")
try:
# LangGraph built-in PNG generation
png_data = app.get_graph().draw_mermaid_png()
with open("patterns/01_reflection/graph.png", "wb") as f:
f.write(png_data)
print("Graph saved as PNG to patterns/01_reflection/graph.png")
except Exception as e:
print(f"Could not save PNG: {e}")
if __name__ == "__main__":
visualize_graph()
print("--- Pattern 01: Reflection ---")
initial_prompt = "Write a fast Python function to calculate the nth Fibonacci number."
inputs = {"messages": [HumanMessage(content=initial_prompt)], "iterations": 0}
for event in app.stream(inputs):
for key, value in event.items():
print(f"\nNode: {key}")
if "messages" in value:
print(f"Content: {value['messages'][-1].content[:200]}...")