{ "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": "/9j/4AAQSkZJRgABAQAAAQABAAD/4gHYSUNDX1BST0ZJTEUAAQEAAAHIAAAAAAQwAABtbnRyUkdCIFhZWiAH4AABAAEAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAACRyWFlaAAABFAAAABRnWFlaAAABKAAAABRiWFlaAAABPAAAABR3dHB0AAABUAAAABRyVFJDAAABZAAAAChnVFJDAAABZAAAAChiVFJDAAABZAAAAChjcHJ0AAABjAAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAAgAAAAcAHMAUgBHAEJYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFlaIAAAAAAAACSgAAAPhAAAts9YWVogAAAAAAAA9tYAAQAAAADTLXBhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABtbHVjAAAAAAAAAAEAAAAMZW5VUwAAACAAAAAcAEcAbwBvAGcAbABlACAASQBuAGMALgAgADIAMAAxADb/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wAARCAEuAL4DASIAAhEBAxEB/8QAHQABAAICAwEBAAAAAAAAAAAAAAYHBQgCAwQBCf/EAFQQAAEEAQIDAgcIDgYHCQEAAAEAAgMEBQYRBxIhEzEIFiJBVZTRFBUXMlFhk7MJIzY3QlZxdHWBkbTS4TM4UlNydmJzgpKhscEkJkNERVSEhaKk/8QAGgEBAAIDAQAAAAAAAAAAAAAAAAMFAQIEBv/EADYRAAIBAQQHBQgCAgMAAAAAAAABAgMEETFREhMVIUFhkRRScdHwBSIygaGxweE0YlNjM7Lx/9oADAMBAAIRAxEAPwD9U0REAREQHCaaOvE+WV7Y42Auc952DQO8k+YLG+NWE9MUPWme1Yvip97LVv6JtfVOUQ8X8X6Np/QN9igtFop2WEZ1E3pNrdyu8zus9m7Qm77riw/GrCemKHrTPanjVhPTFD1pntVeeL+L9G0/oG+xPF/F+jaf0DfYuDatn7kuqOvZ39voWH41YT0xQ9aZ7U8asJ6YoetM9qrzxfxfo2n9A32J4v4v0bT+gb7E2rZ+5Lqhs7+30LD8asJ6YoetM9qeNWE9MUPWme1V54v4v0bT+gb7E8X8X6Np/QN9ibVs/cl1Q2d/b6Fh+NWE9MUPWme1PGrCemKHrTPaq88X8X6Np/QN9ieL+L9G0/oG+xNq2fuS6obO/t9Cw/GrCemKHrTPavfUuV78ImrTx2ITuBJE8Oaf1hVb4v4v0bT+gb7FIuEcTINNXI42Njjbk7gaxg2AHbO7gu2z2qlalLQTV12PM5rRZdRFSvvJsiIukrwiIgCIiAIiIAiIgCIiAi3FT72WrP0Ta+qcsAs/xU+9lqz9E2vqnKM379bF0bF27YiqU60bpprE7wyOJjRu5znHoAACST0ACp/a/wDw0fGX2gXfs7CR3ooQOOfDdxAHEHSxJ6ADNVv419i438OZ5WRx6/0vJI8hrWNzNYlxPcAOdeb1c8mWunHMxWnuONTWFXLWcHpnUN2jUhtSVsiasbK190DzG9kLnSg8xeCAHhm+x67ArF8LeNmV1Vwcoaty2kM2+8+vA8wY2rFJ7udIduaswTOPZgkbmQtIHU9xKw2i9EaorcWbGQp6Wl0Jpq1Dc9+Kwysdqpkp3lvYzwQMJ7J/xnPcWs332O56mP0dDcRG8DcJoexpeeE6es04bkdTLwxtz9GN7xLHE8PDog5ojJEnJuCW7rr0KeCu4cfHn65HNpTxd/Hh4FjTeERp2lobUmpb+OzOM8XLEVbKYm3Vay7WdIYwwlnOWuaRK1wLXEEb7bnosLrrj1nMFZ0WcfoXPiHM5l1GWC3BXbYmhbXdKOyabA5XPOxHabbCOQODTy7wCTgrqc6V4pUMZoavp2tqGbEWsXiqt2u5rBDKwTMeQ4Na/aMyHbdp59g5xCuDjZpvO5U6NzOnsYM1c09nGZGTGiwyB9iEwzQvDHvIaHDtQ4BxAOx6po0oyV2/58l+RpVJLfu+XPyLFpzutVIJnwSVnyMa8wTbc8ZI35XbEjcdx2JHzldygzeNOjKMccGd1Tp/T2ZYxvuvFXczVE1SXYF0b9n7bg9Oi5Hjnw3HfxB0sP8A7qt/GuTVzyOjTjmTdZThR9z1/wDSlz65yjuFzmN1JjIcliMhVymPn37K3SmbNFJsS08r2kg7EEdD3gqRcKPuev8A6UufXOV/7I3Kqny/JX2/fTXiTRERXpQBERAEREAREQBERAEREBFuKn3stWfom19U5R9zQ9pa4BzSNiD3FTzN4ivn8NexlsONW7A+vKGO2dyPaWnY+Y7FRb4KaPpjN+u/yXLa7MrXThHS0XFv63eRY2S0RoJqXEwvvfVP/lofowvooVgdxXi3/wAAWZ+Cmj6Yzfrv8k+Cmj6Yzfrv8lV7If8AlXRnd2+lkzGosl8FNH0xm/Xf5LG6l4b1sXpzK3IMzmhPXqSzRl1zcczWEjcbfKE2P/tXRmdoUsmEUF8GrDT8UOBmkNU5zN5aTLZOoZrDoLPZsLu0c3o3bp0AVmfBTR9MZv13+SbH/wBq6MbQpZMw76VeRxc6CJzj3ksBJXH3BV/9tD/uBZr4KaPpjN+u/wAk+Cmj6Yzfrv8AJNkP/KujMdvpZMxbI2xMDWNDGjuDRsAstwo+56/+lLn1zlx+Cmj6Yzfrv8lINNabq6VxnuGo+aSMyvmc+xJzvc57i5xJ/KVZWSyKyKd8777uDOO1WqFaCjFGWREXYVgREQBERAEREAREQBERAEREAREQBYXWv3G578wsfVuWaWF1r9xue/MLH1bkBVXgT/1V+Hf5g766RXeqQ8Cf+qvw7/MHfXSK70AREQBERAEREAREQBERAEREAREQBERAEREAREQBYXWv3G578wsfVuWaVfcWeKWjNG4TLYrP6uwWDyljGTSQ0clk4a88rHNe1rmse4OILmuAIHUgjzICI+BP/VX4d/mDvrpFd61n8C7ivomr4OvDzCT6xwEOabCykcdJlIG2BYkmk7OHsy7m537HlbtufMCtmEAREQBERAEREAREQBERAEREAREQBERAEREARdNy5Xx1Sa1anjrVoWl8k0zwxjGjqS5x6AD5SoRc4k27byMLhjNB1At5KU1mO+drOVzyP8Qb8vXpvJGnKSvWHQkhTnUd0VeT1aBfZTuC02Vw+B4n0GOkdjGNxGTAO4ZA6RzoJNu4ASSPaT3kyM+RbaHWerSelbCgfIXTFYPW5zXELSGY01maOFnxeVqvqWGAyh3K4bbtJ32cO8HzEA+Zb6pd5dSfslbI0M+xpcCzr3ipPrnJVi/C6W2dXLx5Mt5w+1j5+zbu/p1Duz+VfqwteuCui7vAXQNTSWmq2NfQglknfYuve+eeR7ty+RzWtBO3K0bNHRrR5lPBrLVu43r4Xb5jMmqXeXUdkrZFkoq9rcRczScDk8DHPX/CmxVntHt+cxPa3cefyXE/ID55rh8zSz9FlyhYbYruJbzAEFrh3tc07Frh3FpAI84Wsqcoq/Fct5DOlOn8SPaiIoiIIiIAiIgCIiAIiIAiIgCIiAIiICs9Q5V2qM/Yh5icTi5uyZGHeTYsN2LnuHnEbvJaD3ODnbEhhHFYbRz3S6dqyv8A6WZ0k0v+sdI5z9/n5iVFuOediw+ioq3PmBey1+vjaMWCtipZmsPfu1gmPSNpDXczu8N3267KS0bqjhwju6eeJ6WnFUqSuLCRamt1ZrvS2huKWFsX8lDJgMljeay3IOyl2hQsNifZLLDo2ukLIy9wJbu3c9Tygry5HV2d0fg+IGW0rnM5k9OW7WFxWIzWevTuEBlkc206OSdrtmt7Ro7Usds534QYGjnuGvS4et/kbeItYNRYLiZw/wBC8QMlYyVihhY9M23xtk1PPlbcV1o3jmilfBE+IcvOCA4jflIA2UnxuPyGnuJukcM7UufyVDV2nr78gy7kZHFk8QrkTQEEdg7aZ42i5WjoQAQCsGyq8i7MPmqGocbDkMZcgyFCcExWazw+OQAkEtcOhG4PULkcq7SN4ZqNxbUBAyMXNsx0PQGUj+1GPK387QR18nanPA+05Xw/A7Tt2G3kLEl+vzSR270s8URbJINoo3uLYh1O4YBuQN+5XNkIY7FCzFNsYnxOa/cbjlIIKlpS0Jq/Dj4C5VqfvLEtVFgdA2ZrmhdOWLBJnlxtaSQnv5jE0n/is8t5x0JOOR5l7giItDAREQBERAEREAREQBERAEREBVD6DtO5/IYqQFsUssl2k4n+kie7me0f6t7y3bzNdH/aAWO1fozDa8wzsVnaQvUjIyYN7R8b2SNO7XsewhzHA9zmkFWpqHTtTUlEV7PPE9jueGzCQJYH+Z7CQQD1IIIIIJBBBINJ6B198IVbL2tOV5NUYvGX5cc/JUYTXEkjAC7ljmLeYAnl3Y5w3G/QKaUdc9OL38eHz+f3Lqz2mEoaFQjmoeAWn6+j9QY/S+Fow5DLMrif3yt2+ysuhl7Rj5XxyCTtAS4iUHn323JA2WJ4YcEMpiW6jraufSs6fy1WOqdNRZG5k6oILi+YyWyXhzgWjZoAHKD1PVW4b+QadjpvNb/NWB/5OXTbzdmhVms2cDl69aFjpJZZa4axjQNy4ku2AAG+617PVyOnSoXp3oi+K4E6IwuDzWIq4eT3BmavuK8ye/ZmfLBs4CMPfIXNaA92waRtudlI5NG4ebN4bLvp75HD15qtGbtX/aYpQwSN232duI2dXAkbdNtyvJpXXVfW+n6WcwOMyeWxFxhfXuVa4dHIAS07Hm8xBBHmIIWWF/IEgeLmaG/y1R/Esdnq5G6qUVg0YfR/DTTegLWSnwGPOOOQkMs8TLEroeYuc4lkbnFke5c4kMDQd1l8zXnysTMPTcW3clvA1zCOaKM9JJf9hpJ/xco/CC9NajqTKuDKmBkotPfZyszI2N/IxjnvcfmIaD8o83fofVWmMfxKzGhzbtWtcVacd61LZoyRMlru22MD9uTs2ucBsHHyidy5wcVvGGqanO69cMepzVrTCnHRp4llVq8dSvFBCwRwxMDGMHc1oGwH7F2IihxKIIiIAiIgCIiAIiIAiIgCIiALGam1DU0lp3J5vIdr7hx1aS3P2ELpZOzY0udysaCXHYHoAsFxV1/Z4caOsZijpzJ6tvCWOtXxWIj5pZZZHBrOY9zGbkczz3DzFebEcOpY+J97XdrPZt8lzGxUYdP2LDfcVFvRzy1jOjnlzRu4k7eVsSCNgMLgxmOMT9Aa7x+cz+jMBFFLbs6WtU44ZrrnDljE5duQwDnPKNw7mY4FpAKs6vWhqR9nBEyGMuc/kjaGjmcS5x2HnJJJPnJJXaiALUD7JLx1+DrhIzRuNnDM3qvmgl5T5UVJu3an/bJEfXvBk26hbfql+P3g08N+LkN7U+rNOe+2cx+Jkr1rXu6zD2cbO0kYOWORrTs57juQT1+TZAap/Yt+O3JLluFWVsHZ/Pk8Nzu6Aj+nhH6tpAB8kh86/RRaeeBZ4L/DObhRw64jHTr26zEJue+keStsPaiR7d+zEoZtyjYt5diNwQdytw0AWPzuFiz2Jv0XzT0zbrSVTbpv7OeJr27F0b9jyuHeD5iAfMsgiAqejLqPgniNC6Xgxuo+JtKxafRvainsRPtUWOf9qkmadjIwc3KXDubGSSSQDZ9PJU8i6wKlqC0a8pgmEMgf2Ug2JY7Y9HDcdD16helVjk+E7dEVtc6g4X43E4rXeozHZmlyXaup2J2OJ5nsa7yS4PfuW7buIcd0BZyKCYzitiqOoNN6N1RkaGL4g5XGtvHEQue6N7gD2ohkLQHcrmv2G/MQ0nbbcqdoAiIgCIiAIiIAiIgCh+tNVakwmotK43A6Slz9XJ2yzJZI22QQ4yu0Aukdvu57jv5LQOux6jpvMFV2Tp6d0p4QeJzN/VFurm9U4mTDY/T0nM6tZdXd7okmb0Ia9rCG9SAQfOSgM7w74UYfhnb1LbxtjI3LmoMi/JXbGSuPsOLz0axvMdmtY3Zo8+zQCTsFNERAEREAUc4kZOphuH2pbt+1DSpw46w6Sew8MYwdm7qSegXv1RqjE6L0/fzmcvwYvE0YjNZt2HcrI2j/AJnuAA6kkAbkrWHD4POeGzm62f1NVtYDglSmE2JwEpMdjUT2nybFkDq2Dpu1nn7+vxiBYngUsczwWOHQcC0+95Ox+QyvIV3LpqVIKFWGrVhjrVoWNjihhYGsjYBsGtA6AAAAALuQBERAEREB5rGMqW7dW1NVhltVS4153xtc+EuHK4scRu3cdDt3hVFYzGe8G/h9Pc1Bf1NxYgdl9mTVKEb7tGnJ13kazbtRG4O3cAD5bQA0Dpcyw+sq2SuaQzlfD3o8Xl5aM8dO9N8SvOY3COR3Q9Gu2J6Hu7kBlmP7RjXbEcw32cNiPyhclH+H9PL4/Q2n62fycWazkNGGO9kYP6OzOGAPkbsB0c7cjoO/uUgQBERAEREAREQBaEcbPsiOmdM8SoMfY4O3cpmdMTyMbLqC7BVsULe7mSCIRtsNI5Q3aRr/ACtzsNgC7fOexFVjMk0rIYx3ukcGgfrK0v8ADz8GrB8ZcC/Wmk7mOGt8ZETYrxTs5spXaPibA9ZWgeSe8jyevk7bKMpYIEy8Bzwm9aeEtj9YXtVYrD46ripasNKTEwSxiV7xKZQ/tJX78obFttt8Y9/m2iWqX2PLT9Hhx4OGPOTswY3J5q7Yyc9a3I2OVgJEUe7XbEAsia8fM/fzrZjxqwnpih60z2rbVz7rM3Myqw2sdY4XQGmchqDUORhxWHoRmWxanOzWDzAecknYBo3JJAAJK8mqOIunNHaUympMplq0OHxkBsWbEb+05GD5A3ckkkAAdSSAtedH6Ez/AIWmp6GveI+Pmw/DejKLGmdE2Rs64fwbt5vc7cdWxnpsf7JJk0aa3MwdWmdJZ3wydRUtY64o2MLwioyixp/SNjyZMu4fFuXB/YPe2PuIPnbuZNrIomQRMjjY2ONgDWsYNg0DuAHmC5NaGNDWgBoGwA8y+rACIiAIiIAiIgC0F8Ojwr+JfCPWme0E3Aadm0dnsSWU7lmvYdYkglhMU4L2zNaHtk7QAcvQchIO/Xe23m8dQfyWb9Wu/wDsyzNaf+JWsHh8cLMVxt4MyW8PapXdVade69Qigma+aeMgCeBgBJJc0BwaASXRtA71uoTe9IzcypfAR8LLiDxH1jpfhkNPYJmk8NjCyxdqwzixBWhgLIiXOmc0udKYGk8vcXdOu4/QZah/Y+OE2N4M8JZMxnbFbH6s1JIJ7Ve1K2OarAwkQwuaTu09XPIOx8sAjdq2uq53G3pBHWyFWw8/gxTtcf2Ao6c1vaYuZ7kRFoYCIiAKI6u1dPUt+9OJ5DkC0PnsyDmjqMPd0/Ckd+C3uA3c7pytfKrE7KteWaQ7RxtL3H5gNyqh00+S3io8jPsbeSPu2dw36ukAIHXzNbytHzNCljdGLqPhh4+vwdtloqrP3sEH6ao25u3yMZy9sjY2cjtM89d+gI5Wj5mgD5l3e8GMH/p1T6BvsUC44cTcrwzp6WlxWFsZh+UzlXHzNgZG5wje7ymN55GASPHRpPk7777dCu7P8a6eCvUMYzTWocrnrFBuSnw2NqxTWaMBOwM320MB5g5oa17iS07AqN1aksZPqXd8I+7hcTf3gxno6p9A32J7wYz0dU+gb7FBLnHzTpxmnLOGq5PVNnUFd9qhj8PXD7DoWbCR7xI5jYw1xDTzuB5ug3KxHwwnVWseF/i9bmr4jM3cnUydG1XaydkletITDI1wLo3skZ1AI327yD111k+8zLnAsm5o/B343MnxNRwcNi5sLWu7tvjDY9xI/Ws9g9UW9MSxwZO1Jfw73Bjbc55pqhJ2Bkd+HH1ALj5Te9xc0ksrzRfF+hr3O26OKwmbdj4Jp67c3LVa2jLJC/kka1/OXdHAgczQDsdt1OpoWWInxSsbJG9pa5jhuHA9CCpI1pYTd69YZEc6UK8S0EUT4Y5CS5pSOvPIZZsfNLRc8kkubG4iMknqSY+Tcnz79/epYk46EnHI85KLi3FhERaGoREQHnyGQr4qlPctyiGtC0vkkd5gP+f5B3qtMnkshq9xkty2cdjHb9njYn9m57fMZnt8on/Qa4NG+x5tt1luJVv3Vk8FhjsYZXSX5mnfyhCWBg+kkY/8sYWOUzk6UU44vjksN3P9XFvY6EWtZJGMr6Xw1VvLDiaUY8/LXYN/y9Oq7feDGejqn0DfYqR01xX1VqfiHr6eTH6io4HS/NBDiK9Gi4WXiGNx55HSl5lJl52Na5rORo5juSFl9Kcea7dOaMqOp6h1hnc1gxl4n08dBFLYjDmtc57BKI4neWDtzcvmDiSAYXUqPe5PqWCqRLX94MZ6OqfQN9i65tMYey3llxVKQbbeVXYf+ih7ONFG/ovE6kwuntQ6ir5GSSJtPGUmusQPjc5sjZg97WsLXMc07u7x03WAucYXalyvCy3py1PVxWdzFujkKtqs1kw7GtYLoZGuBLHMliG/KR8XvIPUqtRYSfU2c4FtYy7kNIuEmPknv49u3aYqaXm8kd/YPd1a/wCRpPIe7yN+cWXjMlWzFCC7TlE1aZvOx4BHT5CD1BHcQdiCCD1Vdr3cObRp57N4kECBzY8hCwb+S55c2UfMC5gd0873frmUnWi3LFcc/Hz8eRW2yhFR1kUWAiIoSoPNkagyGPtVSdhPE6Mn5NwR/wBVU2lZHP05jQ9rmSxwNhlY4bFr2DleD+RzSFcSrrVWBl05kbOVqQumxVt/a3I4hu+tLsAZQ3zxu28rbq13lbEOcWzRWnB01jivL1lcWFjqqnNxlxKx45aXzOpNO4SxgKTMnksJnKWYbj3TNhNpsMm742vd5LXFpOxcduijEtXXGnOIN7W+N0PJlvGHE16lvDnJ1orFCxXfLyEvc7s3RubL15HEgt7irorWYbsDJ68rJ4ZBzMkicHNcPlBHQrsXK71uZcuCbvvNctG8KNY8HZtIZ6liYtW5GDEXcbl8dTtx13RvsXPdgfA6Uta5rXucwglpI2I37lywXCnWen8lpLVcmLr3ct405PNZTEV7jG+5Ir0TotmSO2a8xN5HO225jzbb962LRYvNVRiijdK6O1RT42DMY7S0ui9PyyXH5sNy0c9TLucNoJo67SezmLtnueWsO24JdvuryReWnWm1hYfj8bIRVB5LmRjPkQt32dHG4d8pG4AHxPjO/Ba+SEHUfLi8g3GjFtskvCmuRp23cIIbeyFiwzcbEsDuzafyERhw+YhTNdFKnBjqcFStE2CtBG2KKJg2axjRsAPmAAXepaktObkjzc5acnLMIiKM0CIiAr3iFXdBqzT94g9lLBZpEgdO0PZyM/8AzFL+xeNTnU2n4dTYiSlK8xO5mywzNG7opGkOY8fkI6jzjcHoSq6Zblp3hjMoyOnlgCexDvJmaO+SIn4ze75xvsdipZp1IJx4Y/e/1+S6sVVOOreJAND6Py+HzXFOe5U7GLN5b3TQd2rHdtH7jhj5uhPL5bHDZ2x6b93VRHg5wx1LpTPcObOUxvuWHEaHkw913bxP7K2Z67hHs1x5vJjeeZu7enf1CvlFynfq1u9czWMcJtW1cDputkdMSajwlbNZu1kdMxZGGIWRPZfJUmfzPEcjGtLiY3O3BeDykjYctJcJtZ6UwulZ4tL1o7OA1jeyfvRVvxCN1K1HK0GF52H2vt9uVwaT2Z2HUb7NIl5pqY43+vSC9Ogq5s61zFsA9nWpw1ebboXuc97h+pvIf9oLFTXZJrgx2NiF7LPALawdsIwe58ruvIwec7bnbZoc7ZpsPS+nYtM4ptVknbzve6axYLeUzSu6udtudh3ADc7NAG/RdUE6cHKXFXLz/H/hyW2qlDVrFmXREURSBERARjJ8N8Dk7MlkVpaNmQ7vmx9iSuXnfclwYQHHfzkFY/4J8f6XzQ/+afYpuinVeot2kSKrOKuUmQj4J8f6Xzfrp9ifBPj/AEvm/XT7FN0TX1MzbXVO8yHQ8KsGCDadfyTQQezuXpXRnb5WAhp/IQVLKtSCjWjr1oY69eJoayKJoaxgHcAB0AXai0lUnPdJkcpSl8TvCIijNQiIgCIiALxZfC0M9TNXI1Ibtcnm7OZgcAfMR8h+cdV7UWU3F3oELfwnxAJ9z3MvUZ5mR5GVwH5Ocu2UU4qaHj0lww1hnMfmcw2/jMPcu13SW+Zokjge9u426jdo6K31BOPX3jOIv+XMj+6yKbX1MyXXVO8yHcEtJePXB7RWo8rmcu/J5XD1btl0VvkaZJImucQ3boNyeinEfCjEg/b72XtM7iyTIyNB/wBwtKwvgw/1cuGX+XKH1DFZya+pmNdU7zPBh8Fj9P1fc2Opw04SeYtibtzH5XHvJ+c9V70RQtuTvbIsQiIsAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCgnHr7xnEX/LmR/dZFO1BOPX3jOIv+XMj+6yIDGeDD/Vy4Zf5cofUMVnKsfBh/q5cMv8uUPqGKzkAREQBERAEREAREQBERAEREAREQBERAEREAREQBUx4RnFvQ2H4ZcRNOX9Z6eo6hOAuwjE2crBHbMklVxjZ2ReH8zg5pA23PMNu8K51+bn2UjgYaGaxPFLGV/tN/kxuXLB3TNb9olP8AiY0sJ7h2bB3uQG13gp8UtGZPgvw107T1dgreoI8DTrvxMGThfbbKysHPYYg7nDmhjyRtuAx2/cVeq/Mz7F1wPfm9Y5PifkI3Np4UPoYwnoJLMjCJXfkZE/l285l/0V+maAIiIAiIgCIiAIiIAiIgCIiAIiIAiIgCrzLa31ANTZjH42tjfc2Plji57Rk53l0LJCfJ6fh7fqVhqqnfdxrD88g/dIElN0qU5pb0uPikV9vrTs9B1KeO49njfq/+4wn7Zk8b9X/3GE/bMvqKq2hVyXQ8vta1Zroj5436v/uMJ+2ZRjibh8txb0HmdI5+nh5MVlIDDKYjIJIzuC2RhIID2uDXAkEbgbg9ylCJtCrkug2tas10REOE+ncpwZ0BidH6dq4luLxzHNY+y+V00rnOLnPe4AAuc5xJ2AHmAAACl3jfq/8AuMJ+2ZfViYdVYuxqm1pyO1zZmrUjvTVuzeOWGRz2Mdzbcp3dG8bA7jbqOoWdoVsl0Mr2ra3g/ojK+N+r/wC4wn7Zk8b9X/3GE/bMvqLG0KuS6GNrWrNdEc8frjUTNQ4alka2MNW/ZdXLqpk52EQySA+V0/8AD2/WrFVUy/dZpD9Jv/dLCtZWsajq0oTaubTw8WensFedooKpUx3hERCxCIiAIiIAiIgCIiAIiIAqqd93GsPzyD90gVqqqnfdxrD88g/dIFHW/j1PBf8AZFR7V/iy+X3PaiiWoaOu58pI/BZvTtLHEN5Icjh57MwO3Xd7LUYI37vJG3zrGnGcUthtqXSA+X/u9a6//wBy87cszxSgmviX18iE8dc3qfKcSdIaIwT5IK2RpXMhOIcy/EyWnRGNrYm2Y4pHjlD3PLWgEjbygBsY3exXEHCxaD0/qTUV2g3JaulrxSYzLvsWTjzRmd2E1gxRmQh7X7OLeYDlIIc0OFu5HhjFr/BwVOIcWMz1yrZM9S1iYJ8ea/kgDkcJ3yNd8bcteAQQNunX3Y7hRpXFUsDUq4rs4MHcffoA2JXGKw9r2vkLi4l5Ilk35y7q7fv2UynFJI7I14Qgo3YX8PHfj+CiMxq7UWlfGnQ9LUmSZXdrPGYKtm7tg2LlCpcrRTSBssm5c4EuYxz9yO0HXoFL+GekmaM8I3VmPjyuWy8Z0zjpBNmbrrczd7Fkcokf5RbuCdiTsXHbpsBZOW4UaTz0GpYMjhorsOo5IpcoyZ73Cw+NjGRuA5vILWxs2LOXq0Hv6rCUODdHQjrN7QEdPDZ20yKvYu5k28k2WBhcWtIdYa7mBd0dzd3TqNtmnFpr1wMuvCUHFbm1lx3b/oyyEUBbjOKIDubUukSdvJ209aGx38//AG7r03XuwNDX0OWgfms5pu5jBzdtBQwtivM7yTy8sj7cgHlbE7tO4BHTfcQ3LM4nBJfEvr5Eil+6zSH6Tf8AulhWsqpl+6zSH6Tf+6WFay9DQ/j0/B/dntPZP8VeLCIilLgIiIAiIgCIiAIiIAiIgCqfLR5HGaz1JKMJkrkFuxDLDNVhD2OaK0TD13H4TXD9SthFt7rjKE1en5p/ggr0IWiDpzwKl987/wCLeb9VH8Se+d/8W836qP4lbSLn7NZu4+pWbIs3Pr+ipffO/wDi3m/VR/Envnf/ABbzfqo/iVtInZrN3H1GyLNz6/oqX3zv/i3m/VR/Envnf/FvN+qj+JW0idms3cfUbIs3Pr+ipffO/wDi3m/VR/Envnf/ABbzfqo/iVtInZrN3H1GyLNz6/oqWg3I5TVmmne8eTqw1br55prUAYxjfc0zO/f+09o/WraRFP7qioQVyXneWVChCzw1cMD/2Q==", "text/plain": [ "" ] }, "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 }