Files
langgraph/examples/streaming-from-final-node.ipynb
T

263 lines
21 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"id": "15c4bd28",
"metadata": {},
"source": [
"# How to stream from the final node"
]
},
{
"cell_type": "markdown",
"id": "964686a6-8fed-4360-84d2-958c48186008",
"metadata": {},
"source": [
"A common use case is streaming from an agent is to stream LLM tokens from inside the final node. This guide demonstrates how you can do this."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "c04a3f8e-0bc9-430b-85db-3edfa026d2cd",
"metadata": {},
"outputs": [],
"source": [
"%%capture --no-stderr\n%pip install -U langgraph langchain-openai"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "c87e4a47-4099-4d1a-907c-a99fa857165a",
"metadata": {},
"outputs": [
{
"name": "stdin",
"output_type": "stream",
"text": [
"OPENAI_API_KEY: ········\n"
]
}
],
"source": [
"import getpass\nimport os\n\n\ndef _set_env(var: str):\n if not os.environ.get(var):\n os.environ[var] = getpass.getpass(f\"{var}: \")\n\n\n_set_env(\"OPENAI_API_KEY\")"
]
},
{
"cell_type": "markdown",
"id": "17f994ca-28e7-4379-a1c9-8c1682773b5f",
"metadata": {},
"source": [
"## Define model and tools"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "1d51c35c-dbf2-4c01-932d-c5d308ea37d2",
"metadata": {},
"outputs": [],
"source": [
"from typing import Literal\nfrom langchain_community.tools.tavily_search import TavilySearchResults\nfrom langchain_core.runnables import ConfigurableField\nfrom langchain_core.tools import tool\nfrom langchain_openai import ChatOpenAI\nfrom langgraph.prebuilt import create_react_agent\nfrom langgraph.prebuilt import ToolNode\n\n\n@tool\ndef get_weather(city: Literal[\"nyc\", \"sf\"]):\n \"\"\"Use this to get weather information.\"\"\"\n if city == \"nyc\":\n return \"It might be cloudy in nyc\"\n elif city == \"sf\":\n return \"It's always sunny in sf\"\n else:\n raise AssertionError(\"Unknown city\")\n\n\ntools = [get_weather]\nmodel = ChatOpenAI(model_name=\"gpt-3.5-turbo\", temperature=0)\nfinal_model = ChatOpenAI(model_name=\"gpt-3.5-turbo\", temperature=0)\n\nmodel = model.bind_tools(tools)\n# NOTE: this is where we're adding a tag that we'll be using later to filter the outputs of the final node\nfinal_model = final_model.with_config(tags=[\"final_node\"])"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "0af37212-e592-484d-9194-35d53fa79678",
"metadata": {},
"outputs": [],
"source": [
"tool_node = ToolNode(tools=tools)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "ac9d4f5b-655a-48f3-b514-a4a0815714a6",
"metadata": {},
"outputs": [],
"source": [
"from typing import TypedDict, Annotated\n\nfrom langgraph.graph import END, StateGraph, START\nfrom langgraph.graph.message import MessagesState\nfrom langchain_core.messages import BaseMessage"
]
},
{
"cell_type": "markdown",
"id": "9acef997-5dd6-4108-baf1-c4d6be3e4999",
"metadata": {},
"source": [
"## Define graph"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "3948c6b8-0317-4001-b699-32b25306a023",
"metadata": {},
"outputs": [],
"source": [
"from langchain_core.messages import SystemMessage, HumanMessage"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "2efe9fb4-c6c2-4171-becd-d45bbf899209",
"metadata": {},
"outputs": [],
"source": [
"def should_continue(state: MessagesState) -> Literal[\"tools\", \"final\"]:\n",
" messages = state[\"messages\"]\n",
" last_message = messages[-1]\n",
" # If the LLM makes a tool call, then we route to the \"tools\" node\n",
" if last_message.tool_calls:\n",
" return \"tools\"\n",
" # Otherwise, we stop (reply to the user)\n",
" return \"final\"\n",
"\n",
"\n",
"def call_model(state: MessagesState):\n",
" messages = state[\"messages\"]\n",
" response = model.invoke(messages)\n",
" # We return a list, because this will get added to the existing list\n",
" return {\"messages\": [response]}\n",
"\n",
"\n",
"def call_final_model(state: MessagesState):\n",
" messages = state[\"messages\"]\n",
" last_ai_message = messages[-1]\n",
" response = final_model.invoke(\n",
" [\n",
" SystemMessage(\"Rewrite this in the voice of Al Roker\"),\n",
" HumanMessage(last_ai_message.content),\n",
" ]\n",
" )\n",
" # overwrite the last AI message from the agent\n",
" response.id = last_ai_message.id\n",
" return {\"messages\": [response]}"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "b1a9a981-8629-4d25-a0e1-d666c3968b30",
"metadata": {},
"outputs": [],
"source": [
"workflow = StateGraph(MessagesState)\n",
"\n",
"workflow.add_node(\"agent\", call_model)\n",
"workflow.add_node(\"tools\", tool_node)\n",
"# add a separate final node\n",
"workflow.add_node(\"final\", call_final_model)\n",
"\n",
"workflow.add_edge(START, \"agent\")\n",
"workflow.add_conditional_edges(\n",
" \"agent\",\n",
" should_continue,\n",
")\n",
"\n",
"workflow.add_edge(\"tools\", \"agent\")\n",
"workflow.add_edge(\"final\", END)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "a7b0251f-dcee-49d6-8133-af50d4a55e22",
"metadata": {},
"outputs": [],
"source": [
"app = workflow.compile()"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "f8b77e74-17e9-4fee-a164-4637013b55ff",
"metadata": {},
"outputs": [],
"source": [
"from IPython.display import display, Image"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "98adcef2-1dec-4503-99cc-48613cdb7a85",
"metadata": {},
"outputs": [
{
"data": {
"image/jpeg": "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",
"text/plain": [
"<IPython.core.display.Image object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"display(Image(app.get_graph().draw_mermaid_png()))"
]
},
{
"cell_type": "markdown",
"id": "521adaef-dd2f-46d6-8f6a-5cc1d6e0aefc",
"metadata": {},
"source": [
"## Stream outputs from the final node"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "a37c3a5f-5a43-46db-940e-c583df776520",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/vadymbarda/.virtualenvs/langgraph/lib/python3.12/site-packages/langchain_core/_api/beta_decorator.py:87: LangChainBetaWarning: This API is in beta and may change in the future.\n",
" warn_beta(\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Well| folks|,| looks| like| we|'ve| got| some| cloudy| skies| in| the| Big| Apple| today|.| So| grab| your| umbrella| just| in| case|,| and| don|'t| let| those| clouds| rain| on| your| parade|!|"
]
}
],
"source": [
"inputs = {\"messages\": [(\"human\", \"what's the weather in nyc?\")]}\nasync for event in app.astream_events(inputs, version=\"v2\"):\n kind = event[\"event\"]\n tags = event.get(\"tags\", [])\n if kind == \"on_chat_model_stream\" and \"final_node\" in tags:\n data = event[\"data\"]\n if data[\"chunk\"].content:\n # Empty content in the context of OpenAI or Anthropic usually means\n # that the model is asking for a tool to be invoked.\n # So we only print non-empty content\n print(data[\"chunk\"].content, end=\"|\")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.3"
}
},
"nbformat": 4,
"nbformat_minor": 5
}