mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-09-03 08:18:47 +02:00
28 KiB
28 KiB
In [1]:
%%capture --no-stderr
%pip install --quiet -U langchain langchain_openai tavily-python[1m[[0m[34;49mnotice[0m[1;39;49m][0m[39;49m A new release of pip is available: [0m[31;49m23.3.1[0m[39;49m -> [0m[32;49m23.3.2[0m [1m[[0m[34;49mnotice[0m[1;39;49m][0m[39;49m To update, run: [0m[32;49mpip install --upgrade pip[0m
In [2]:
import os
import getpass
os.environ["OPENAI_API_KEY"] = getpass.getpass("OpenAI API Key:")
os.environ["TAVILY_API_KEY"] = getpass.getpass("Tavily API Key:")OpenAI API Key: ········ Tavily API Key: ········
In [ ]:
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = getpass.getpass("LangSmith API Key:")In [1]:
from langchain_community.tools.tavily_search import TavilySearchResults
tools = [TavilySearchResults(max_results=1)]In [2]:
from langgraph.prebuilt import ToolExecutor
tool_executor = ToolExecutor(tools)In [3]:
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 [4]:
model = model.bind_tools(tools)In [12]:
from langgraph.prebuilt import ToolInvocation
from langchain_core.messages import ToolMessage
# Define the function that determines whether to continue or not
def should_continue(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 continue
else:
return "continue"
# Define the function that calls the model
async def call_model(messages):
response = await model.ainvoke(messages)
# We return a list, because this will get added to the existing list
return response
# Define the function to execute tools
async def call_tool(messages):
# Based on the continue condition
# we know the last message involves a function call
last_message = messages[-1]
tool_call = last_message.tool_calls[0]
# We construct an ToolInvocation from the function_call
action = ToolInvocation(
tool=tool_call["name"],
tool_input=tool_call["args"],
)
# We call the tool_executor and get back a response
response = await tool_executor.ainvoke(action)
# We use the response to create a FunctionMessage
function_message = ToolMessage(
content=str(response), name=action.tool, tool_call_id=tool_call["id"]
)
# We return a list, because this will get added to the existing list
return function_messageIn [13]:
from langgraph.graph import MessageGraph, END
# Define a new graph
workflow = MessageGraph()
# Define the two nodes we will cycle between
workflow.add_node("agent", call_model)
workflow.add_node("action", call_tool)
# 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,
# Finally we pass in a mapping.
# The keys are strings, and the values are other nodes.
# END is a special node marking that the graph should finish.
# What will happen is we will call `should_continue`, and then the output of that
# will be matched against the keys in this mapping.
# Based on which one it matches, that node will then be called.
{
# If `tools`, then we call the tool node.
"continue": "action",
# Otherwise we finish.
"end": END,
},
)
# 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 [14]:
from IPython.display import Image, display
try:
display(Image(app.get_graph(xray=True).draw_mermaid_png()))
except:
# This requires some extra dependencies and is optional
passIn [15]:
from langchain_core.messages import HumanMessage
inputs = [HumanMessage(content="what is the weather in sf")]
async for event in app.astream_events(inputs, version="v1"):
kind = event["event"]
if kind == "on_chat_model_stream":
content = event["data"]["chunk"].content
if content:
# Empty content in the context of OpenAI means
# that the model is asking for a tool to be invoked.
# So we only print non-empty content
print(content, end="|")
elif kind == "on_tool_start":
print("--")
print(
f"Starting tool: {event['name']} with inputs: {event['data'].get('input')}"
)
elif kind == "on_tool_end":
print(f"Done tool: {event['name']}")
print(f"Tool output was: {event['data'].get('output')}")
print("--")The| current| weather| in| San| Francisco| is| as| follows|: |-| Temperature|:| |55|.|0|°F| (|12|.|8|°C|) |-| Condition|:| Over|cast| |-| Wind|:| |11|.|9| mph| (|19|.|1| k|ph|)| from| W|SW| |-| Hum|idity|:| |96|% |-| Cloud| Cover|:| |100|% |-| Fe|els| like|:| |52|.|4|°F| (|11|.|4|°C|) |-| Visibility|:| |9|.|0| miles| (|16|.|0| km|) |-| UV| Index|:| |1|.|0| |For| more| details|,| you| can| visit| [|Weather| API|](|https|://|www|.weather|api|.com|/|).|
In [ ]: