mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-08-17 21:25:46 +02:00
27 KiB
27 KiB
In [ ]:
%%capture --no-stderr
%pip install --quiet -U langgraph langchain-anthropicIn [1]:
import getpass
import os
def _set_env(var: str):
if not os.environ.get(var):
os.environ[var] = getpass.getpass(f"{var}: ")
_set_env("ANTHROPIC_API_KEY")In [2]:
os.environ["LANGCHAIN_TRACING_V2"] = "true"
_set_env("LANGCHAIN_API_KEY")In [3]:
from typing import Annotated
from typing_extensions import TypedDict
from langgraph.graph.message import add_messages
# Add messages essentially does this with more
# robust handling
# def add_messages(left: list, right: list):
# return left + right
class State(TypedDict):
messages: Annotated[list, add_messages]In [4]:
from langchain_core.tools import tool
@tool
def search(query: str):
"""Call to surf the web."""
# This is a placeholder, but don't tell the LLM that...
return ["The weather will be sunny with a high of 27 C."]
tools = [search]In [5]:
from langgraph.prebuilt import ToolNode
tool_node = ToolNode(tools)In [6]:
from langchain_openai import ChatOpenAI
model = ChatOpenAI(temperature=0)In [7]:
from langchain_core.pydantic_v1 import BaseModel, Field
class Response(BaseModel):
"""Final response to the user"""
temperature: float = Field(description="the temperature")
other_notes: str = Field(description="any other notes about the weather")
# Bind to the actual tools + the response format!
model = model.bind_tools(tools + [Response], tool_choice="any")In [8]:
import operator
from typing import Annotated, Sequence, TypedDict
from langchain_core.messages import BaseMessage
class AgentState(TypedDict):
messages: Annotated[Sequence[BaseMessage], operator.add]In [9]:
from typing import Literal
# Define the function that determines whether to continue or not
def route(state: AgentState) -> Literal["action", "__end__"]:
messages = state["messages"]
last_message = messages[-1]
# If there is no function call, then we finish
if not last_message.tool_calls:
return "__end__"
# Otherwise if there is, we need to check what type of function call it is
if last_message.tool_calls[0]["name"] == Response.__name__:
return "__end__"
# Otherwise we continue
return "action"
# Define the function that calls the model
def call_model(state: AgentState):
messages = state["messages"]
response = model.invoke(messages)
# We return a list, because this will get added to the existing list
return {"messages": [response]}In [10]:
from langgraph.graph import StateGraph, START
# Define a new graph
workflow = StateGraph(AgentState)
# Define the two nodes we will cycle between
workflow.add_node("agent", call_model)
workflow.add_node("action", tool_node)
# Set the entrypoint as `agent`
# This means that this node is the first one called
workflow.add_edge(START, "agent")
# We now add a conditional edge
workflow.add_conditional_edges(
# First, we define the start node. We use `agent`.
# This means these are the edges taken after the `agent` node is called.
"agent",
# Next, we pass in the function that will determine which node is called next.
route,
)
# We now add a normal edge from `tools` to `agent`.
# This means that after `tools` is called, `agent` node is called next.
workflow.add_edge("action", "agent")
# Finally, we compile it!
# This compiles it into a LangChain Runnable,
# meaning you can use it as you would any other runnable
app = workflow.compile()In [11]:
from IPython.display import Image, display
display(Image(app.get_graph(xray=True).draw_mermaid_png()))In [12]:
from langchain_core.messages import HumanMessage
inputs = {"messages": [HumanMessage(content="what is the weather in sf")]}
for output in app.stream(inputs, stream_mode="values"):
last_msg = output["messages"][-1]
last_msg.pretty_print()
print("\n---\n")================================[1m Human Message [0m================================= what is the weather in sf --- ==================================[1m Ai Message [0m================================== Tool Calls: search (call_j6mePdJkK2b9TaLKtSfjC9t1) Call ID: call_j6mePdJkK2b9TaLKtSfjC9t1 Args: query: weather in San Francisco --- =================================[1m Tool Message [0m================================= Name: search ["The weather will be sunny with a high of 27 C."] --- ==================================[1m Ai Message [0m================================== Tool Calls: Response (call_k2aKLoYXQjEkRFn2ZEpVN4Hl) Call ID: call_k2aKLoYXQjEkRFn2ZEpVN4Hl Args: temperature: 27 other_notes: Sunny weather ---
In [ ]: