mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-08-20 22:52:29 +02:00
296 lines
9.1 KiB
Plaintext
296 lines
9.1 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "b23ced4e-dc29-43be-9f94-0c36bb181b8a",
|
|
"metadata": {},
|
|
"source": [
|
|
"# How to stream events from within a tool"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "7044eeb8-4074-4f9c-8a62-962488744557",
|
|
"metadata": {},
|
|
"source": [
|
|
"If your LangGraph graph needs to use tools that call LLMs (or any other LangChain `Runnable` objects -- other graphs, LCEL chains, retrievers, etc.), you might want to stream events from the underlying `Runnable`. This guide shows how you can do that."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "a37f60af-43ea-4aa6-847a-df8cc47065f5",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Setup"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"id": "47f79af8-58d8-4a48-8d9a-88823d88701f",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%%capture --no-stderr\n",
|
|
"%pip install -U langgraph langchain-openai"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"id": "0cf6b41d-7fcb-40b6-9a72-229cdd00a094",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdin",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"OPENAI_API_KEY: ········\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"import getpass\n",
|
|
"import os\n",
|
|
"\n",
|
|
"\n",
|
|
"def _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": "e3d02ebb-c2e1-4ef7-b187-810d55139317",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Define graph and tools"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "d74a1760-a063-4d05-8c6f-9d16bc31fa82",
|
|
"metadata": {},
|
|
"source": [
|
|
"We'll use a prebuilt ReAct agent for this guide"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"id": "083757a9-26d7-481e-8f3d-3e34bcba154b",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from langchain_core.callbacks import Callbacks\n",
|
|
"from langchain_core.prompts import ChatPromptTemplate\n",
|
|
"from langchain_core.tools import tool\n",
|
|
"\n",
|
|
"from langgraph.prebuilt import create_react_agent\n",
|
|
"from langchain_openai import ChatOpenAI"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "9378fd4a-69e4-49e2-b34c-a98a0505ea35",
|
|
"metadata": {},
|
|
"source": [
|
|
"<div class=\"admonition warning\">\n",
|
|
" <p class=\"admonition-title\">ASYNC IN PYTHON<=3.10</p>\n",
|
|
" <p>\n",
|
|
"Any Langchain RunnableLambda, a RunnableGenerator, or Tool that invokes other runnables and is running async in python<=3.10, will have to propagate callbacks to child objects manually. This is because LangChain cannot automatically propagate callbacks to child objects in this case.\n",
|
|
" \n",
|
|
"This is a common reason why you may fail to see events being emitted from custom runnables or tools.\n",
|
|
" </p>\n",
|
|
"</div>"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"id": "2cb38dd9-74d8-456d-9e39-4655f2bf3f37",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"@tool\n",
|
|
"async def get_items(\n",
|
|
" place: str, callbacks: Callbacks\n",
|
|
") -> str: # <--- Accept callbacks (Python <= 3.10)\n",
|
|
" \"\"\"Use this tool to look up which items are in the given place.\"\"\"\n",
|
|
" template = ChatPromptTemplate.from_messages(\n",
|
|
" [\n",
|
|
" (\n",
|
|
" \"human\",\n",
|
|
" \"Can you tell me what kind of items i might find in the following place: '{place}'. \"\n",
|
|
" \"List at least 3 such items separating them by a comma. And include a brief description of each item..\",\n",
|
|
" )\n",
|
|
" ]\n",
|
|
" )\n",
|
|
" chain = template | llm.with_config(\n",
|
|
" {\n",
|
|
" \"run_name\": \"Get Items LLM\",\n",
|
|
" \"tags\": [\"tool_llm\"],\n",
|
|
" \"callbacks\": callbacks, # <-- Propagate callbacks (Python <= 3.10)\n",
|
|
" }\n",
|
|
" )\n",
|
|
" chunks = [chunk async for chunk in chain.astream({\"place\": place})]\n",
|
|
" return \"\".join(chunk.content for chunk in chunks)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "17279b8a-049d-483d-af63-8a875098e71f",
|
|
"metadata": {},
|
|
"source": [
|
|
"We're adding a custom tag (`tool_llm`) to our LLM runnable within the tool. This will allow us to filter events that we'll stream from the compiled graph (`agent`) Runnable below"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 5,
|
|
"id": "7254310e-7016-45f7-9795-6d52a1160086",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"llm = ChatOpenAI(model_name=\"gpt-3.5-turbo\")\n",
|
|
"tools = [get_items]\n",
|
|
"agent = create_react_agent(llm, tools=tools)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "b7d88960-a66b-4699-adee-c12d40b4318a",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Stream events from the graph"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"id": "31fe94ab-80de-4729-843e-5a0fe1bb52c0",
|
|
"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": [
|
|
"1. Books - A collection of written or printed works bound together with covers. They can be fiction or non-fiction and come in various genres.\n",
|
|
"\n",
|
|
"2. Picture frames - A decorative border for a photograph or artwork, typically made of wood, metal, or plastic. Picture frames are used to display and protect a picture or painting.\n",
|
|
"\n",
|
|
"3. Candles - A cylinder of wax with a central wick that is lit to produce light or fragrance. Candles are often used for decoration, ambiance, or religious ceremonies."
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"async for event in agent.astream_events(\n",
|
|
" {\"messages\": [(\"human\", \"what items are on the shelf?\")]}, version=\"v2\"\n",
|
|
"):\n",
|
|
" tags = event.get(\"tags\", [])\n",
|
|
" if event[\"event\"] == \"on_chat_model_stream\" and \"tool_llm\" in tags:\n",
|
|
" print(event[\"data\"][\"chunk\"].content, end=\"\", flush=True)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "ebd8902e-935b-4724-8b5d-551b7674fd34",
|
|
"metadata": {},
|
|
"source": [
|
|
"Let's inspect the last event to get the final list of messages from the agent"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 7,
|
|
"id": "ca382c1f-b1c7-4c8a-bd9b-7a873b891b3e",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"final_messages = event[\"data\"][\"output\"][\"messages\"]"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 8,
|
|
"id": "3fa7d768-5a84-475a-950e-fd351a44841b",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"================================\u001b[1m Human Message \u001b[0m=================================\n",
|
|
"\n",
|
|
"what items are on the shelf?\n",
|
|
"==================================\u001b[1m Ai Message \u001b[0m==================================\n",
|
|
"Tool Calls:\n",
|
|
" get_items (call_5CAMZ3asoLsZm9ocMbCOWxYQ)\n",
|
|
" Call ID: call_5CAMZ3asoLsZm9ocMbCOWxYQ\n",
|
|
" Args:\n",
|
|
" place: shelf\n",
|
|
"=================================\u001b[1m Tool Message \u001b[0m=================================\n",
|
|
"Name: get_items\n",
|
|
"\n",
|
|
"1. Books - A collection of written or printed works bound together with covers. They can be fiction or non-fiction and come in various genres.\n",
|
|
"\n",
|
|
"2. Picture frames - A decorative border for a photograph or artwork, typically made of wood, metal, or plastic. Picture frames are used to display and protect a picture or painting.\n",
|
|
"\n",
|
|
"3. Candles - A cylinder of wax with a central wick that is lit to produce light or fragrance. Candles are often used for decoration, ambiance, or religious ceremonies.\n",
|
|
"==================================\u001b[1m Ai Message \u001b[0m==================================\n",
|
|
"\n",
|
|
"The items on the shelf are:\n",
|
|
"1. Books\n",
|
|
"2. Picture frames\n",
|
|
"3. Candles\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"for message in final_messages:\n",
|
|
" message.pretty_print()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "d7f9457c-5665-4cd5-9a99-d54c84270616",
|
|
"metadata": {},
|
|
"source": [
|
|
"You can see that the content of the `ToolMessage` is the same as the output we streamed above"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "langgraph",
|
|
"language": "python",
|
|
"name": "langgraph"
|
|
},
|
|
"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
|
|
}
|