mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-08-17 21:25:46 +02:00
29 KiB
29 KiB
In [ ]:
%%capture --no-stderr
%pip install --quiet -U langgraph langchain_anthropicIn [21]:
import os
import getpass
def _set_env(var: str):
if not os.environ.get(var):
os.environ[var] = getpass.getpass(f"{var}: ")
_set_env("ANTHROPIC_API_KEY")In [22]:
os.environ["LANGCHAIN_TRACING_V2"] = "true"
_set_env("LANGCHAIN_API_KEY")In [37]:
from typing_extensions import TypedDict
from typing import Annotated
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 [24]:
from langchain_core.tools import tool
@tool
def search(query: str):
"""Call to surf the web."""
# This is a placeholder for the actual implementation
return ["The answer to your question lies within."]
tools = [search]In [25]:
from langgraph.prebuilt import ToolNode
tool_node = ToolNode(tools)In [26]:
from langchain_openai import ChatOpenAI
# We will set streaming=True so that we can stream tokens
# See the streaming section for more information on this.
model = ChatOpenAI(temperature=0, streaming=True)In [27]:
bound_model = model.bind_tools(tools)In [28]:
# Define the function that determines whether to continue or not
from typing import Literal
def should_continue(state: State) -> Literal["action", "__end__"]:
"""Return the next node to execute."""
last_message = state["messages"][-1]
# If there is no function call, then we finish
if not last_message.tool_calls:
return "__end__"
# Otherwise if there is, we continue
return "action"
# Define the function that calls the model
def call_model(state: State):
response = model.invoke(state["messages"])
# We return a list, because this will get added to the existing list
return {"messages": response}In [29]:
from langgraph.graph import StateGraph, END
# Define a new graph
workflow = StateGraph(State)
# 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.set_entry_point("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.
should_continue,
)
# 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")In [30]:
from langgraph.checkpoint.sqlite import SqliteSaver
memory = SqliteSaver.from_conn_string(":memory:")In [31]:
# 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(checkpointer=memory)In [32]:
from IPython.display import Image, display
try:
display(Image(app.get_graph().draw_mermaid_png()))
except:
# This requires some extra dependencies and is optional
passIn [33]:
from langchain_core.messages import HumanMessage
config = {"configurable": {"thread_id": "2"}}
input_message = HumanMessage(content="hi! I'm bob")
for event in app.stream({"messages": [input_message]}, config, stream_mode="values"):
event["messages"][-1].pretty_print()================================[1m Human Message [0m================================= hi! I'm bob ==================================[1m Ai Message [0m================================== Hello Bob! How can I assist you today?
In [34]:
input_message = HumanMessage(content="what is my name?")
for event in app.stream({"messages": [input_message]}, config, stream_mode="values"):
event["messages"][-1].pretty_print()================================[1m Human Message [0m================================= what is my name? ==================================[1m Ai Message [0m================================== Your name is Bob.
In [35]:
input_message = HumanMessage(content="what is my name?")
for event in app.stream(
{"messages": [input_message]},
{"configurable": {"thread_id": "3"}},
stream_mode="values",
):
event["messages"][-1].pretty_print()================================[1m Human Message [0m================================= what is my name? ==================================[1m Ai Message [0m================================== I'm sorry, I do not know your name as I am an AI assistant and do not have access to personal information.
In [36]:
input_message = HumanMessage(content="You forgot??")
for event in app.stream(
{"messages": [input_message]},
{"configurable": {"thread_id": "2"}},
stream_mode="values",
):
event["messages"][-1].pretty_print()================================[1m Human Message [0m================================= You forgot?? ==================================[1m Ai Message [0m================================== I apologize for the confusion. I am an AI assistant and I do not have the ability to remember information from previous interactions. How can I assist you today, Bob?
In [ ]: