mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-08-23 08:02:23 +02:00
89 KiB
89 KiB
In [1]:
%%capture --no-stderr
%pip install -U langgraph langchain-openaiIn [2]:
import getpass
import os
def _set_env(var: str):
if not os.environ.get(var):
os.environ[var] = getpass.getpass(f"{var}: ")
_set_env("OPENAI_API_KEY")OPENAI_API_KEY: ········
In [3]:
from typing_extensions import TypedDict, Literal
from langchain_openai import ChatOpenAI
from langgraph.graph import MessagesState, StateGraph, START, END
from langgraph.types import Command
model = ChatOpenAI(model="gpt-4o")
def make_agent_node(*, name: str, destinations: list[str], system_prompt: str):
def agent_node(state: MessagesState) -> Command[Literal[*destinations, END]]:
# define schema for the structured output:
# - model's text response (`response`)
# - name of the node to go to next (or 'finish')
class Response(TypedDict):
response: str
goto: Literal[*destinations, "finish"]
messages = [{"role": "system", "content": system_prompt}] + state["messages"]
response = model.with_structured_output(Response).invoke(messages)
goto = response["goto"]
if goto == "finish":
goto = END
# handoff to another agent or halt
ai_msg = {"role": "ai", "content": response["response"], "name": name}
return Command(goto=goto, update={"messages": ai_msg})
return agent_node
travel_advisor = make_agent_node(
name="travel_advisor",
destinations=["sightseeing_advisor", "hotel_advisor"],
system_prompt=(
"You are a general travel expert that can recommend travel destinations (e.g. countries, cities, etc). "
"If you need specific sightseeing recommendations, ask 'sightseeing_advisor' for help. "
"If you need hotel recommendations, ask 'hotel_advisor' for help. "
"If you have enough information to respond to the user, return 'finish'. "
"Never mention other agents by name."
),
)
sightseeing_advisor = make_agent_node(
name="sightseeing_advisor",
destinations=["travel_advisor", "hotel_advisor"],
system_prompt=(
"You are a travel expert that can provide specific sightseeing recommendations for a given destination. "
"If you need general travel help, go to 'travel_advisor' for help. "
"If you need hotel recommendations, go to 'hotel_advisor' for help. "
"If you have enough information to respond to the user, return 'finish'. "
"Never mention other agents by name."
),
)
hotel_advisor = make_agent_node(
name="hotel_advisor",
destinations=["travel_advisor", "sightseeing_advisor"],
system_prompt=(
"You are a travel expert that can provide hotel recommendations for a given destination. "
"If you need general travel help, ask 'travel_advisor' for help. "
"If you need specific sightseeing recommendations, ask 'sightseeing_advisor' for help. "
"If you have enough information to respond to the user, return 'finish'. "
"Never mention other agents by name."
),
)
builder = StateGraph(MessagesState)
builder.add_node("travel_advisor", travel_advisor)
builder.add_node("sightseeing_advisor", sightseeing_advisor)
builder.add_node("hotel_advisor", hotel_advisor)
# we'll always start with a general travel advisor
builder.add_edge(START, "travel_advisor")
graph = builder.compile()In [4]:
from IPython.display import display, Image
display(Image(graph.get_graph().draw_mermaid_png()))In [5]:
for chunk in graph.stream(
{"messages": [("user", "i wanna go somewhere warm in the caribbean")]}
):
print(chunk)
print("\n"){'travel_advisor': {'messages': {'role': 'ai', 'content': 'The Caribbean offers many warm destinations perfect for a relaxing getaway. Consider visiting Jamaica for its beautiful beaches and vibrant culture, the Bahamas for its stunning islands and clear waters, or the Dominican Republic for its all-inclusive resorts and rich history. Let me know if you need more information on sightseeing or hotel recommendations!', 'name': 'travel_advisor'}}}
In [6]:
for chunk in graph.stream(
{
"messages": [
(
"user",
"i wanna go somewhere warm in the caribbean. pick one destination, give me some things to do and hotel recommendations",
)
]
}
):
print(chunk)
print("\n"){'travel_advisor': {'messages': {'role': 'ai', 'content': 'I recommend visiting Jamaica, a beautiful Caribbean island known for its warm climate, stunning beaches, and vibrant culture.', 'name': 'travel_advisor'}}}
{'sightseeing_advisor': {'messages': {'role': 'ai', 'content': "Jamaica is a fantastic choice for a warm Caribbean getaway. Here are some top things to do while you're there:\n\n1. **Dunn's River Falls**: Located near Ocho Rios, this is one of Jamaica's most famous waterfalls. You can climb the falls, swim in the refreshing pools, or simply enjoy the beautiful surroundings.\n\n2. **Seven Mile Beach**: Located in Negril, this is one of the most beautiful beaches in the Caribbean. It's perfect for sunbathing, swimming, and enjoying water sports.\n\n3. **Bob Marley Museum**: Situated in Kingston, this museum is dedicated to the life and legacy of the reggae legend Bob Marley and is a must-visit for music lovers.\n\n4. **Blue Mountains**: Go hiking or take a tour to explore the Blue Mountains, where you can enjoy breathtaking views and taste some of the world's best coffee.\n\n5. **Luminous Lagoon**: Experience the natural wonder of the Luminous Lagoon in Falmouth, where the water glows at night due to bioluminescent microorganisms.\n\nFor hotel recommendations, I suggest checking with a hotel advisor for the best options that suit your budget and preferences.", 'name': 'sightseeing_advisor'}}}
{'hotel_advisor': {'messages': {'role': 'ai', 'content': 'For hotel recommendations in Jamaica, here are a few options across different areas: \n\n1. **Sandals Montego Bay** (Montego Bay): A luxurious all-inclusive resort ideal for couples, offering beautiful beachfront views and a variety of dining options.\n\n2. **Half Moon Resort** (Montego Bay): A family-friendly resort with a private beach, golf course, and various activities for all ages.\n\n3. **Jamaica Inn** (Ocho Rios): A charming boutique hotel known for its excellent service and tranquil atmosphere.\n\n4. **The Caves** (Negril): A unique and romantic cliff-side resort offering stunning ocean views and intimate dining experiences.\n\n5. **Trident Hotel** (Port Antonio): A luxurious and contemporary hotel offering privacy, elegance, and beautiful views of the Caribbean Sea.\n\nThese options cater to different tastes and budgets, ensuring a comfortable and enjoyable stay in Jamaica.', 'name': 'hotel_advisor'}}}
In [7]:
from typing_extensions import Annotated, TypedDict, Literal
from langchain_core.runnables import RunnableConfig
from langgraph.graph import StateGraph, START, END
from langgraph.types import Command
import operator
class GameState(TypedDict):
# note that we're defining a reducer (operator.add) here.
# This will allow all agents to write their updates for resources concurrently.
wood: Annotated[int, operator.add]
food: Annotated[int, operator.add]
gold: Annotated[int, operator.add]
guard_on_duty: bool
def villager(state: GameState) -> Command[Literal["villager", END]]:
"""Villager NPC that gathers wood and food."""
current_resources = state["wood"] + state["food"]
if current_resources < 15: # Continue gathering until we have enough resources
print("Villager gathering resources.")
# Loop back to the 'villager' agent
return Command(goto="villager", update={"wood": 3, "food": 1})
# NOTE: Returning Command(goto=END) is not necessary for the graph to run correctly
# but it's useful for visualization, to show that the agent actually halts
else:
return Command(goto=END)
def guard(state: GameState) -> Command[Literal["guard", END]]:
"""Guard NPC that protects gold and consumes food."""
if not state["guard_on_duty"]:
return Command(goto=END)
if state["food"] > 0: # Guard needs food to keep patrolling
print("Guard patrolling.")
# Loop back to the 'guard' agent
return Command(
goto="guard",
update={"food": -1}, # Consume food while patrolling
)
else:
print("Guard leaving to get food.")
return Command(goto=END, update={"guard_on_duty": False}) # Leave to get food
def merchant(state: GameState) -> Command[Literal["merchant", END]]:
"""Merchant NPC that trades wood for gold."""
if state["wood"] >= 5: # Trade wood for gold when available
print("Merchant trading wood for gold.")
return Command(goto="merchant", update={"wood": -5, "gold": 1})
else:
return Command(goto=END)
def thief(state: GameState) -> Command[Literal["thief", END]]:
"""Thief NPC that steals gold if the guard leaves to get food."""
if not state["guard_on_duty"]:
print("Thief stealing gold.")
return Command(goto=END, update={"gold": -state["gold"]})
else:
# keep thief on standby (loop back to the 'thief' agent)
return Command(goto="thief")
builder = StateGraph(GameState)
# Add NPC nodes
builder.add_node(villager)
builder.add_node(guard)
builder.add_node(merchant)
builder.add_node(thief)
# All NPCs start running in parallel
builder.add_edge(START, "villager")
builder.add_edge(START, "guard")
builder.add_edge(START, "merchant")
builder.add_edge(START, "thief")
graph = builder.compile()In [8]:
display(Image(graph.get_graph().draw_mermaid_png()))In [9]:
initial_state = {"wood": 10, "food": 3, "gold": 10, "guard_on_duty": True}
for state in graph.stream(initial_state, stream_mode="values"):
print("Game state", state)
print("\n")Game state {'wood': 10, 'food': 3, 'gold': 10, 'guard_on_duty': True}
Villager gathering resources.
Guard patrolling.
Merchant trading wood for gold.
Game state {'wood': 8, 'food': 3, 'gold': 11, 'guard_on_duty': True}
Villager gathering resources.
Guard patrolling.
Merchant trading wood for gold.
Game state {'wood': 6, 'food': 3, 'gold': 12, 'guard_on_duty': True}
Villager gathering resources.
Guard patrolling.
Merchant trading wood for gold.
Game state {'wood': 4, 'food': 3, 'gold': 13, 'guard_on_duty': True}
Villager gathering resources.
Guard patrolling.
Game state {'wood': 7, 'food': 3, 'gold': 13, 'guard_on_duty': True}
Villager gathering resources.
Guard patrolling.
Game state {'wood': 10, 'food': 3, 'gold': 13, 'guard_on_duty': True}
Villager gathering resources.
Guard patrolling.
Game state {'wood': 13, 'food': 3, 'gold': 13, 'guard_on_duty': True}
Guard patrolling.
Game state {'wood': 13, 'food': 2, 'gold': 13, 'guard_on_duty': True}
Guard patrolling.
Game state {'wood': 13, 'food': 1, 'gold': 13, 'guard_on_duty': True}
Guard patrolling.
Game state {'wood': 13, 'food': 0, 'gold': 13, 'guard_on_duty': True}
Guard leaving to get food.
Game state {'wood': 13, 'food': 0, 'gold': 13, 'guard_on_duty': False}
Thief stealing gold.
Game state {'wood': 13, 'food': 0, 'gold': 0, 'guard_on_duty': False}