diff --git a/graph_gen/gen_graph.py b/graph_gen/gen_graph.py index e2145b1..be26e4f 100644 --- a/graph_gen/gen_graph.py +++ b/graph_gen/gen_graph.py @@ -200,4 +200,4 @@ def gen_graph(graph_name, graph_spec, memory=None): mem_spec = "" if memory: mem_spec = f"checkpointer={memory}" - return graph_setup + "\n".join(node_code) + "\n\n" + f"{graph_name} = {graph_name}.compile({mem_spec})" \ No newline at end of file + return graph_setup + "\n".join(node_code) + "\n\n" + f"{graph_name} = {graph_name}.compile({mem_spec})" diff --git a/human-in-loop.ipynb b/human-in-loop.ipynb index 947b57d..6a84d1c 100644 --- a/human-in-loop.ipynb +++ b/human-in-loop.ipynb @@ -14,7 +14,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 2, "id": "3498f044-2381-4e02-bc8c-d1b3c4c0dabb", "metadata": {}, "outputs": [], @@ -43,7 +43,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 3, "id": "5e71f0e6-2cf4-4f4b-86eb-07594bedbda2", "metadata": {}, "outputs": [], @@ -58,10 +58,43 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 5, "id": "b8616228-ae71-46a9-82c3-9d54483729fc", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "human_in_loop = StateGraph(AgentState)\n", + "human_in_loop.add_node('call_model', call_model)\n", + "human_in_loop.add_node('ask_human_approval', ask_human_approval)\n", + "human_in_loop.add_node('call_tool', call_tool)\n", + "\n", + "human_in_loop.set_entry_point('call_model')\n", + "\n", + "def after_call_model(state: AgentState):\n", + " if should_call_tool(state):\n", + " return 'ask_human_approval'\n", + " return END\n", + "\n", + "call_model_dict = {'ask_human_approval': 'ask_human_approval', END: END}\n", + "human_in_loop.add_conditional_edges('call_model', after_call_model, call_model_dict)\n", + "\n", + "def after_ask_human_approval(state: AgentState):\n", + " if human_allows_tool_call(state):\n", + " return 'call_tool'\n", + " return END\n", + "\n", + "ask_human_approval_dict = {'call_tool': 'call_tool', END: END}\n", + "human_in_loop.add_conditional_edges('ask_human_approval', after_ask_human_approval, ask_human_approval_dict)\n", + "\n", + "human_in_loop.add_edge('call_tool', 'call_model')\n", + "\n", + "human_in_loop = human_in_loop.compile()\n" + ] + } + ], "source": [ "# Tools\n", "tools = [TavilySearchResults(max_results=1)]\n", @@ -140,7 +173,7 @@ "\n", "# The graph code\n", "graph_code = gen_graph(\"human_in_loop\", graph_spec)\n", - "#print(graph_code)\n", + "print(graph_code)\n", "exec(graph_code)" ] }, diff --git a/introduction.ipynb b/introduction.ipynb index 9a6865e..198c7a2 100644 --- a/introduction.ipynb +++ b/introduction.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": 78, "id": "c3f52963-8ca3-4e11-8cf1-73e522926d66", "metadata": {}, "outputs": [], @@ -27,7 +27,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 2, "id": "6f11d631-8679-4f28-822f-cdf1f2ddc21c", "metadata": {}, "outputs": [], @@ -41,7 +41,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 3, "id": "705d4020-6ee8-44cc-b1a5-8c34e7172fc7", "metadata": {}, "outputs": [], @@ -60,7 +60,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 4, "id": "13cba9af-0572-41df-92f8-d6f56d5b5322", "metadata": {}, "outputs": [], @@ -80,7 +80,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 5, "id": "e58df974-7579-4f25-9d91-66389b94eba2", "metadata": {}, "outputs": [], @@ -101,7 +101,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 6, "id": "bc8c9137-8261-42ea-8e83-3590981d23e2", "metadata": {}, "outputs": [], @@ -116,7 +116,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 7, "id": "e331e10d-ebcf-4144-9bd3-999b4d656dd3", "metadata": {}, "outputs": [ @@ -143,7 +143,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 8, "id": "0bb67a01-cf5c-4625-8c07-6e8c0af50fca", "metadata": {}, "outputs": [], @@ -153,7 +153,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 9, "id": "32e4f36e-72ce-4ade-bd7e-94880e0d456b", "metadata": {}, "outputs": [ @@ -180,7 +180,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 10, "id": "7afb4c9a-7404-4e92-9945-36f372015f08", "metadata": {}, "outputs": [ @@ -188,57 +188,39 @@ "name": "stdin", "output_type": "stream", "text": [ - "User: tell me about langgraph\n" + "User: hi\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "Assistant: I'm afraid I don't have any specific information about \"langgraph.\" This term does not seem to be a widely recognized or commonly used one. Without more context about what exactly you are asking about, I cannot provide any detailed information. If you have additional details about what you are referring to by \"langgraph,\" I'd be happy to try to research and provide more helpful information. Otherwise, I don't have enough information to give a substantive response about this particular term or concept.\n" + "Assistant: Hello! How can I assist you today?\n" ] }, { "name": "stdin", "output_type": "stream", "text": [ - "User: what about claude\n" + "User: tell me a joke\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "Assistant: I'm afraid I don't have any specific information about an individual named Claude. As an AI assistant, I don't have personal knowledge about specific people. I'm happy to try to help with any other questions you might have though!\n" - ] - }, - { - "name": "stdin", - "output_type": "stream", - "text": [ - "User: tell me a story about a dinosaur\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Assistant: Here is a short story about a dinosaur:\n", + "Assistant: Here's a silly joke for you:\n", "\n", - "In the lush, prehistoric forests, a mighty Tyrannosaurus Rex stalked its domain. With each thunderous step, the ground trembled beneath its massive, three-toed feet. Its powerful jaws, lined with serrated teeth, could crush bone with devastating force. \n", + "Why did the tomato turn red? Because it saw the salad dressing!\n", "\n", - "The T-Rex raised its massive head, its fierce golden eyes scanning the landscape for any sign of prey. The scent of a herd of Edmontosaurus filled its nostrils, and a deep, rumbling growl escaped its throat. With incredible speed and agility for its size, the T-Rex broke into a sprint, its short but muscular arms pumping as it gave chase.\n", - "\n", - "The herbivorous Edmontosaurus, sensing the danger, trumpeted a warning and began to flee. But the T-Rex was relentless, closing the distance with each stride. Finally, it caught up to a straggling juvenile and clamped its jaws around the poor creature's neck. The Edmontosaurus let out a gurgling cry before succumbing to the T-Rex's deadly grip.\n", - "\n", - "Tearing into its kill, the mighty Tyrannosaurus feasted, its primal instincts taking over. For this fearsome predator, the ancient forest was its domain, and it reigned supreme over all who dared to cross its path.\n" + "How was that? I tried to come up with a simple, family-friendly pun that would hopefully give you a little chuckle. Let me know if you'd like to hear another joke!\n" ] }, { "name": "stdin", "output_type": "stream", "text": [ - "User: quit\n" + "User: q\n" ] }, { @@ -248,13 +230,6 @@ "Goodbye!\n" ] }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "User: hm that doesn't seem right...\n" - ] - }, { "name": "stdout", "output_type": "stream", @@ -360,7 +335,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 11, "id": "0c52923c-5665-4f8c-a1ba-9799e369c49e", "metadata": {}, "outputs": [], @@ -378,20 +353,20 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 12, "id": "35c8978e-c07d-4dd0-a97b-0ce3a723eea5", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "[{'url': 'https://medium.com/@cplog/introduction-to-langgraph-a-beginners-guide-14f9be027141',\n", - " 'content': 'Nodes: Nodes are the building blocks of your LangGraph. Each node represents a function or a computation step. You define nodes to perform specific tasks, such as processing input, making ...'},\n", - " {'url': 'https://js.langchain.com/docs/langgraph',\n", - " 'content': \"Assuming you have done the above Quick Start, you can build off it like:\\nHere, we manually define the first tool call that we will make.\\nNotice that it does that same thing as agent would have done (adds the agentOutcome key).\\n LangGraph\\n🦜🕸️LangGraph.js\\n⚡ Building language agents as graphs ⚡\\nOverview\\u200b\\nLangGraph is a library for building stateful, multi-actor applications with LLMs, built on top of (and intended to be used with) LangChain.js.\\n Therefore, we will use an object with one key (messages) with the value as an object: { value: Function, default?: () => any }\\nThe default key must be a factory that returns the default value for that attribute.\\n Streaming Node Output\\u200b\\nOne of the benefits of using LangGraph is that it is easy to stream output as it's produced by each node.\\n What this means is that only one of the downstream edges will be taken, and which one that is depends on the results of the start node.\\n\"}]" + "[{'url': 'https://langchain-ai.github.io/langgraph/concepts/low_level/',\n", + " 'content': 'Nodes¶ In LangGraph, nodes are typically python functions (sync or async) where the first positional argument is the state, and (optionally), the second positional argument is a \"config\", containing optional configurable parameters (such as a thread_id). Similar to NetworkX, you add these nodes to a graph using the add_node method:'},\n", + " {'url': 'https://thenewstack.io/develop-a-master-ai-agent-with-langgraph-in-python/',\n", + " 'content': 'Node: Nodes are the fundamental units of computation in LangGraph. Each node performs specific tasks, such as processing user input or generating responses. Nodes can execute various functions, including calling APIs or running code, and they pass updated state information to the next node in the workflow.'}]" ] }, - "execution_count": 4, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -417,7 +392,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 13, "id": "dc5af88b-47d2-43bf-9a2c-6c07506b1732", "metadata": {}, "outputs": [], @@ -464,7 +439,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 14, "id": "12f1fc14-cd91-4cd4-9f2e-1d007f8beafc", "metadata": {}, "outputs": [], @@ -522,7 +497,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 15, "id": "d662df94-66ac-4c6c-92f0-4c93620f1c74", "metadata": {}, "outputs": [], @@ -580,13 +555,61 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 64, + "id": "005fc900-7e0f-499a-91e3-c6aac9152dd5", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "tool_bot = StateGraph(State)\n", + "tool_bot.add_node('chatbot', chatbot)\n", + "tool_bot.add_node('tool_node', tool_node)\n", + "\n", + "tool_bot.set_entry_point('chatbot')\n", + "\n", + "def after_chatbot(state: State):\n", + " if tools_next(state):\n", + " return 'tool_node'\n", + " return 'END'\n", + "\n", + "chatbot_dict = {'tool_node': 'tool_node', 'END': END}\n", + "tool_bot.add_conditional_edges('chatbot', after_chatbot, chatbot_dict)\n", + "\n", + "tool_bot.add_edge('tool_node', 'chatbot')\n", + "\n", + "tool_bot = tool_bot.compile()\n" + ] + } + ], + "source": [ + "def tools_next(state):\n", + " return route_tools(state) == \"tools\"\n", + " \n", + "graph_spec = \"\"\"\n", + "chatbot(State)\n", + " tools_next => tool_node\n", + " => END\n", + "\n", + "tool_node\n", + " => chatbot\n", + "\"\"\"\n", + "\n", + "graph_code = gen_graph(\"tool_bot\", graph_spec)\n", + "print(graph_code)\n", + "exec(graph_code)" + ] + }, + { + "cell_type": "code", + "execution_count": 65, "id": "8b49509c-9d97-457c-a76a-c495fb30ccbc", "metadata": {}, "outputs": [ { "data": { - "image/jpeg": "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", + "image/jpeg": "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", "text/plain": [ "" ] @@ -599,7 +622,7 @@ "from IPython.display import Image, display\n", "\n", "try:\n", - " display(Image(graph.get_graph().draw_mermaid_png()))\n", + " display(Image(tool_bot.get_graph().draw_mermaid_png()))\n", "except Exception:\n", " # This requires some extra dependencies and is optional\n", " pass" @@ -615,41 +638,48 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 66, "id": "051dc374-67cc-4371-9dd1-221e07593148", "metadata": {}, "outputs": [ { - "name": "stdout", + "name": "stdin", "output_type": "stream", "text": [ - "User: what's langgraph all about?\n" + "User: tell me about langgraph\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "Assistant: [{'id': 'toolu_01L1TABSBXsHPsebWiMPNqf1', 'input': {'query': 'langgraph'}, 'name': 'tavily_search_results_json', 'type': 'tool_use'}]\n", - "Assistant: [{\"url\": \"https://langchain-ai.github.io/langgraph/\", \"content\": \"LangGraph is framework agnostic (each node is a regular python function). It extends the core Runnable API (shared interface for streaming, async, and batch calls) to make it easy to: Seamless state management across multiple turns of conversation or tool usage. The ability to flexibly route between nodes based on dynamic criteria.\"}, {\"url\": \"https://blog.langchain.dev/langgraph-multi-agent-workflows/\", \"content\": \"As a part of the launch, we highlighted two simple runtimes: one that is the equivalent of the AgentExecutor in langchain, and a second that was a version of that aimed at message passing and chat models.\\n It's important to note that these three examples are only a few of the possible examples we could highlight - there are almost assuredly other examples out there and we look forward to seeing what the community comes up with!\\n LangGraph: Multi-Agent Workflows\\nLinks\\nLast week we highlighted LangGraph - a new package (available in both Python and JS) to better enable creation of LLM workflows containing cycles, which are a critical component of most agent runtimes. \\\"\\nAnother key difference between Autogen and LangGraph is that LangGraph is fully integrated into the LangChain ecosystem, meaning you take fully advantage of all the LangChain integrations and LangSmith observability.\\n As part of this launch, we're also excited to highlight a few applications built on top of LangGraph that utilize the concept of multiple agents.\\n\"}]\n", - "Assistant: Based on the search results, LangGraph is a framework-agnostic Python and JavaScript library that extends the core Runnable API from the LangChain project to enable the creation of more complex workflows involving multiple agents or components. Some key things about LangGraph:\n", - "\n", - "- It makes it easier to manage state across multiple turns of conversation or tool usage, and to dynamically route between different nodes/components based on criteria.\n", + "Assistant: [{'id': 'toolu_01TY96r1orTrRirS8w2ocJb1', 'input': {'query': 'langgraph'}, 'name': 'tavily_search_results_json', 'type': 'tool_use'}]\n", + "Assistant: [{\"url\": \"https://blog.langchain.dev/langgraph-cloud/\", \"content\": \"LangGraph is a framework for building agentic and multi-agent applications with LLMs, and LangGraph Cloud is a scalable and reliable infrastructure for deploying them. Learn how LangGraph helps you design, debug, and monitor complex agentic workflows with LLMs.\"}, {\"url\": \"https://github.com/langchain-ai/langgraph\", \"content\": \"LangGraph is a library for creating stateful, multi-actor applications with LLMs, using cycles, controllability, and persistence. Learn how to use LangGraph with examples, integration with LangChain, and streaming support.\"}]\n", + "Assistant: Based on the search results, here's a summary of what LangGraph is:\n", "\n", - "- It is integrated with the LangChain ecosystem, allowing you to take advantage of LangChain integrations and observability features.\n", + "LangGraph is a framework and library for building agentic and multi-agent applications using large language models (LLMs). Key features of LangGraph include:\n", "\n", - "- It enables the creation of multi-agent workflows, where different components or agents can be chained together in more flexible and complex ways than the standard LangChain AgentExecutor.\n", + "- Enabling the design, deployment, and monitoring of complex workflows involving multiple interacting agents/actors powered by LLMs.\n", + "- Providing capabilities for stateful, persistent applications that can maintain memory and context over time.\n", + "- Supporting controllability, where the overall system's behavior can be directed and debugged.\n", + "- Integrating with the LangChain library for building LLM-powered applications.\n", + "- Offering cloud-based infrastructure through LangGraph Cloud for scalable and reliable deployment of LangGraph-based apps.\n", "\n", - "- The core idea is to provide a more powerful and flexible framework for building LLM-powered applications and workflows, beyond what is possible with just the core LangChain tools.\n", - "\n", - "Overall, LangGraph seems to be a useful addition to the LangChain toolkit, focused on enabling more advanced, multi-agent style applications and workflows powered by large language models.\n" + "In essence, LangGraph aims to make it easier to build sophisticated, multi-agent applications that leverage the capabilities of large language models in a robust and managed way. It provides a framework for designing, deploying, and monitoring these types of complex AI-powered systems.\n" + ] + }, + { + "name": "stdin", + "output_type": "stream", + "text": [ + "User: q\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "User: neat!\n" + "Goodbye!\n" ] }, { @@ -696,7 +726,7 @@ " if user_input.lower() in [\"quit\", \"exit\", \"q\"]:\n", " print(\"Goodbye!\")\n", " break\n", - " for event in graph.stream({\"messages\": [(\"user\", user_input)]}):\n", + " for event in tool_bot.stream({\"messages\": [(\"user\", user_input)]}):\n", " for value in event.values():\n", " if isinstance(value[\"messages\"][-1], BaseMessage):\n", " print(\"Assistant:\", value[\"messages\"][-1].content)" @@ -785,7 +815,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 67, "id": "6baafdf6-6803-4305-9381-9dc970468a4d", "metadata": {}, "outputs": [], @@ -807,19 +837,10 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 68, "id": "e6a51f1e-00de-4701-8931-de8cf19294ae", "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/wfh/code/lc/langchain/libs/core/langchain_core/_api/beta_decorator.py:87: LangChainBetaWarning: The method `ChatAnthropic.bind_tools` is in beta. It is actively being worked on, so the API may change.\n", - " warn_beta(\n" - ] - } - ], + "outputs": [], "source": [ "from typing import Annotated\n", "\n", @@ -874,7 +895,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 20, "id": "a06548bf-81fa-4436-b4c1-f68601fb4187", "metadata": {}, "outputs": [], @@ -892,13 +913,49 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 70, + "id": "7e637076-1664-4baa-bc80-eb9a5eaa62f3", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "tool_bot = StateGraph(State)\n", + "tool_bot.add_node('chatbot', chatbot)\n", + "tool_bot.add_node('tool_node', tool_node)\n", + "\n", + "tool_bot.set_entry_point('chatbot')\n", + "\n", + "def after_chatbot(state: State):\n", + " if tools_next(state):\n", + " return 'tool_node'\n", + " return 'END'\n", + "\n", + "chatbot_dict = {'tool_node': 'tool_node', 'END': END}\n", + "tool_bot.add_conditional_edges('chatbot', after_chatbot, chatbot_dict)\n", + "\n", + "tool_bot.add_edge('tool_node', 'chatbot')\n", + "\n", + "tool_bot = tool_bot.compile(checkpointer=memory)\n" + ] + } + ], + "source": [ + "graph_code = gen_graph(\"tool_bot\", graph_spec, memory=\"memory\")\n", + "print(graph_code)\n", + "exec(graph_code)" + ] + }, + { + "cell_type": "code", + "execution_count": 71, "id": "761d15fb-d5e2-4d50-a630-126d77e77294", "metadata": {}, "outputs": [ { "data": { - "image/jpeg": "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", + "image/jpeg": "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", "text/plain": [ "" ] @@ -911,7 +968,7 @@ "from IPython.display import Image, display\n", "\n", "try:\n", - " display(Image(graph.get_graph().draw_mermaid_png()))\n", + " display(Image(tool_bot.get_graph().draw_mermaid_png()))\n", "except Exception:\n", " # This requires some extra dependencies and is optional\n", " pass" @@ -927,7 +984,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 72, "id": "be7b5abb-04ef-4d53-83d1-d4d3139cc43a", "metadata": {}, "outputs": [], @@ -945,7 +1002,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 73, "id": "dba1b168-f8e0-496d-9bd6-37198fb4776e", "metadata": {}, "outputs": [ @@ -958,7 +1015,7 @@ "Hi there! My name is Will.\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "\n", - "It's nice to meet you, Will! I'm an AI assistant created by Anthropic. I'm here to help you with any questions or tasks you may have. Please let me know how I can assist you today.\n" + "It's nice to meet you, Will! As an AI assistant, I'm here to help you with any questions or tasks you may have. Please feel free to ask me anything, and I'll do my best to provide helpful and informative responses.\n" ] } ], @@ -966,7 +1023,7 @@ "user_input = \"Hi there! My name is Will.\"\n", "\n", "# The config is the **second positional argument** to stream() or invoke()!\n", - "events = graph.stream(\n", + "events = tool_bot.stream(\n", " {\"messages\": [(\"user\", user_input)]}, config, stream_mode=\"values\"\n", ")\n", "for event in events:\n", @@ -985,7 +1042,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 74, "id": "f5447778-53d7-47f3-801b-f47bcf2185a0", "metadata": {}, "outputs": [ @@ -998,7 +1055,7 @@ "Remember my name?\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "\n", - "Of course, your name is Will. It's nice to meet you again!\n" + "Yes, I remember your name is Will. It's a pleasure to meet you!\n" ] } ], @@ -1006,7 +1063,7 @@ "user_input = \"Remember my name?\"\n", "\n", "# The config is the **second positional argument** to stream() or invoke()!\n", - "events = graph.stream(\n", + "events = tool_bot.stream(\n", " {\"messages\": [(\"user\", user_input)]}, config, stream_mode=\"values\"\n", ")\n", "for event in events:\n", @@ -1025,7 +1082,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 75, "id": "4527cf9a-b191-4bde-858a-e33a74a48c55", "metadata": {}, "outputs": [ @@ -1038,13 +1095,13 @@ "Remember my name?\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "\n", - "I'm afraid I don't actually have the capability to remember your name. As an AI assistant, I don't have a persistent memory of our previous conversations or interactions. I respond based on the current context provided to me. Could you please restate your name or provide more information so I can try to assist you?\n" + "I'm afraid I don't actually have a way to remember your name. As an AI assistant, I don't have a persistent memory of previous conversations or users. I respond based on the current context provided to me. If you'd like, you can reintroduce yourself and I'll do my best to assist you going forward.\n" ] } ], "source": [ "# The only difference is we change the `thread_id` here to \"2\" instead of \"1\"\n", - "events = graph.stream(\n", + "events = tool_bot.stream(\n", " {\"messages\": [(\"user\", user_input)]},\n", " {\"configurable\": {\"thread_id\": \"2\"}},\n", " stream_mode=\"values\",\n", @@ -1065,29 +1122,29 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 76, "id": "0be77c25-1423-4f2d-9b2d-28530cc761a4", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "StateSnapshot(values={'messages': [HumanMessage(content='Hi there! My name is Will.', id='aad97d7f-8845-4f9e-b723-2af3b7c97590'), AIMessage(content=\"It's nice to meet you, Will! I'm an AI assistant created by Anthropic. I'm here to help you with any questions or tasks you may have. Please let me know how I can assist you today.\", response_metadata={'id': 'msg_01VCz7Y5jVmMZXibBtnECyvJ', 'model': 'claude-3-haiku-20240307', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 375, 'output_tokens': 49}}, id='run-66cf1695-5ba8-4fd8-a79d-ded9ee3c3b33-0'), HumanMessage(content='Remember my name?', id='ac1e9971-dbee-4622-9e63-5015dee05c20'), AIMessage(content=\"Of course, your name is Will. It's nice to meet you again!\", response_metadata={'id': 'msg_01RsJ6GaQth7r9soxbF7TSpQ', 'model': 'claude-3-haiku-20240307', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 431, 'output_tokens': 19}}, id='run-890149d3-214f-44e8-9717-57ec4ef68224-0')]}, next=(), config={'configurable': {'thread_id': '1', 'thread_ts': '2024-05-06T22:23:20.430350+00:00'}}, parent_config=None)" + "StateSnapshot(values={'messages': [HumanMessage(content='Hi there! My name is Will.', id='d2337453-6eec-40b7-8fd8-cdbc3482f9e0'), AIMessage(content=\"It's nice to meet you, Will! As an AI assistant, I'm here to help you with any questions or tasks you may have. Please feel free to ask me anything, and I'll do my best to provide helpful and informative responses.\", response_metadata={'id': 'msg_012KQnCZZafvtRKJQ6ssub4p', 'model': 'claude-3-haiku-20240307', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 375, 'output_tokens': 54}}, id='run-80f60f8b-e98f-45ad-8b8d-baa89f656854-0', usage_metadata={'input_tokens': 375, 'output_tokens': 54, 'total_tokens': 429}), HumanMessage(content='Remember my name?', id='2f01ca04-be33-4c10-bf85-4580d5fa922c'), AIMessage(content=\"Yes, I remember your name is Will. It's a pleasure to meet you!\", response_metadata={'id': 'msg_01HbM3pXQhtCHyGyMGstr9eP', 'model': 'claude-3-haiku-20240307', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 436, 'output_tokens': 20}}, id='run-c729ed33-658b-43b6-9027-1441949c1823-0', usage_metadata={'input_tokens': 436, 'output_tokens': 20, 'total_tokens': 456})]}, next=(), config={'configurable': {'thread_id': '1', 'thread_ts': '1ef4e885-d429-6382-8004-2961f65728d3'}}, metadata={'source': 'loop', 'writes': {'chatbot': {'messages': [AIMessage(content=\"Yes, I remember your name is Will. It's a pleasure to meet you!\", response_metadata={'id': 'msg_01HbM3pXQhtCHyGyMGstr9eP', 'model': 'claude-3-haiku-20240307', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 436, 'output_tokens': 20}}, id='run-c729ed33-658b-43b6-9027-1441949c1823-0', usage_metadata={'input_tokens': 436, 'output_tokens': 20, 'total_tokens': 456})]}}, 'step': 4}, created_at='2024-07-30T15:28:25.893737+00:00', parent_config={'configurable': {'thread_id': '1', 'thread_ts': '1ef4e885-cba2-6ace-8003-1169c0161bf9'}})" ] }, - "execution_count": 10, + "execution_count": 76, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "snapshot = graph.get_state(config)\n", + "snapshot = tool_bot.get_state(config)\n", "snapshot" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 77, "id": "c106bd09-f155-4e15-9120-c60c834106e5", "metadata": {}, "outputs": [ @@ -1097,7 +1154,7 @@ "()" ] }, - "execution_count": 11, + "execution_count": 77, "metadata": {}, "output_type": "execute_result" } @@ -1188,19 +1245,10 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 28, "id": "5a81608a-373a-4339-b1c6-65b73a92b983", "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/wfh/code/lc/langchain/libs/core/langchain_core/_api/beta_decorator.py:87: LangChainBetaWarning: The method `ChatAnthropic.bind_tools` is in beta. It is actively being worked on, so the API may change.\n", - " warn_beta(\n" - ] - } - ], + "outputs": [], "source": [ "from typing import Annotated\n", "\n", @@ -1257,7 +1305,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 29, "id": "b0883e32-1a39-4ce9-ae32-bbd66708fd84", "metadata": {}, "outputs": [], @@ -1273,7 +1321,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 30, "id": "9f318020-ab7e-415b-a5e2-eddec6d9f3a6", "metadata": {}, "outputs": [ @@ -1286,10 +1334,10 @@ "I'm learning LangGraph. Could you do some research on it for me?\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "\n", - "[{'text': \"Okay, let's do some research on LangGraph:\", 'type': 'text'}, {'id': 'toolu_01Be7aRgMEv9cg6ezaFjiCry', 'input': {'query': 'LangGraph'}, 'name': 'tavily_search_results_json', 'type': 'tool_use'}]\n", + "[{'text': \"Okay, let's look into LangGraph for you. I'll perform a search to find some information about it.\", 'type': 'text'}, {'id': 'toolu_0152kHipaXh2nu3PBsVtGMfJ', 'input': {'query': 'LangGraph'}, 'name': 'tavily_search_results_json', 'type': 'tool_use'}]\n", "Tool Calls:\n", - " tavily_search_results_json (toolu_01Be7aRgMEv9cg6ezaFjiCry)\n", - " Call ID: toolu_01Be7aRgMEv9cg6ezaFjiCry\n", + " tavily_search_results_json (toolu_0152kHipaXh2nu3PBsVtGMfJ)\n", + " Call ID: toolu_0152kHipaXh2nu3PBsVtGMfJ\n", " Args:\n", " query: LangGraph\n" ] @@ -1317,17 +1365,17 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 31, "id": "9bb7af46-9b4f-4bb1-b8b9-e9ddf7dbc82c", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "('action',)" + "('tools',)" ] }, - "execution_count": 4, + "execution_count": 31, "metadata": {}, "output_type": "execute_result" } @@ -1347,7 +1395,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 32, "id": "3facda0a-e6ad-4b28-b627-753ad8c90c15", "metadata": {}, "outputs": [ @@ -1356,10 +1404,11 @@ "text/plain": [ "[{'name': 'tavily_search_results_json',\n", " 'args': {'query': 'LangGraph'},\n", - " 'id': 'toolu_01Be7aRgMEv9cg6ezaFjiCry'}]" + " 'id': 'toolu_0152kHipaXh2nu3PBsVtGMfJ',\n", + " 'type': 'tool_call'}]" ] }, - "execution_count": 5, + "execution_count": 32, "metadata": {}, "output_type": "execute_result" } @@ -1381,7 +1430,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 33, "id": "effb95d9-b7d5-40c5-9253-253d193b23b2", "metadata": {}, "outputs": [ @@ -1392,18 +1441,19 @@ "=================================\u001b[1m Tool Message \u001b[0m=================================\n", "Name: tavily_search_results_json\n", "\n", - "[{\"url\": \"https://github.com/langchain-ai/langgraph\", \"content\": \"LangGraph is a Python package that extends LangChain Expression Language with the ability to coordinate multiple chains across multiple steps of computation in a cyclic manner. It is inspired by Pregel and Apache Beam and can be used for agent-like behaviors, such as chatbots, with LLMs.\"}, {\"url\": \"https://langchain-ai.github.io/langgraph//\", \"content\": \"LangGraph is a library for building stateful, multi-actor applications with LLMs, built on top of (and intended to be used with) LangChain . It extends the LangChain Expression Language with the ability to coordinate multiple chains (or actors) across multiple steps of computation in a cyclic manner. It is inspired by Pregel and Apache Beam .\"}]\n", + "[{\"url\": \"https://blog.langchain.dev/langgraph-cloud/\", \"content\": \"LangGraph is a framework for building agentic and multi-agent applications with LLMs, and LangGraph Cloud is a scalable and reliable infrastructure for deploying them. Learn how LangGraph helps you design, debug, and monitor complex agentic workflows with LLMs.\"}, {\"url\": \"https://langchain-ai.github.io/langgraph/\", \"content\": \"LangGraph is a framework for creating stateful, multi-actor applications with LLMs, using cycles, controllability, and persistence. Learn how to use LangGraph to build agent and multi-agent workflows with examples, features, and integration with LangChain.\"}]\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "\n", - "Based on the search results, LangGraph seems to be a Python library that extends the LangChain library to enable more complex, multi-step interactions with large language models (LLMs). Some key points:\n", + "The search results provide a good overview of what LangGraph is - it seems to be a framework for building applications that use large language models (LLMs) in a more structured and stateful way, allowing for the creation of agentic and multi-agent workflows. \n", "\n", - "- LangGraph allows coordinating multiple \"chains\" (or actors) over multiple steps of computation, in a cyclic manner. This enables more advanced agent-like behaviors like chatbots.\n", - "- It is inspired by distributed graph processing frameworks like Pregel and Apache Beam.\n", - "- LangGraph is built on top of the LangChain library, which provides a framework for building applications with LLMs.\n", + "Some key points about LangGraph:\n", "\n", - "So in summary, LangGraph appears to be a powerful tool for building more sophisticated applications and agents using large language models, by allowing you to coordinate multiple steps and actors in a flexible, graph-like manner. It extends the capabilities of the base LangChain library.\n", + "- It is designed to help developers create more complex applications using LLMs, beyond simple conversational interfaces.\n", + "- It provides features like controllability, persistence, and multi-agent coordination to enable the development of richer, more capable AI-powered systems.\n", + "- LangGraph is closely integrated with the LangChain framework, which provides utilities for working with LLMs.\n", + "- LangGraph Cloud is a hosted infrastructure service for deploying and running LangGraph-based applications.\n", "\n", - "Let me know if you need any clarification or have additional questions!\n" + "Overall, LangGraph appears to be a promising framework for developers looking to push the boundaries of what is possible with large language models, by providing a more robust and scalable architecture for building agentic AI systems. Let me know if you need any clarification or have additional questions!\n" ] } ], @@ -1504,19 +1554,10 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 34, "id": "faa345c6-38a2-42e8-9035-9cf56f7bb5b1", "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/wfh/code/lc/langchain/libs/core/langchain_core/_api/beta_decorator.py:87: LangChainBetaWarning: The method `ChatAnthropic.bind_tools` is in beta. It is actively being worked on, so the API may change.\n", - " warn_beta(\n" - ] - } - ], + "outputs": [], "source": [ "from typing import Annotated\n", "\n", @@ -1579,7 +1620,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 35, "id": "a6b3bcae-dd04-49da-a4ef-e05634657faf", "metadata": {}, "outputs": [ @@ -1589,10 +1630,10 @@ "text": [ "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "\n", - "[{'id': 'toolu_01DTyDpJ1kKdNps5yxv3AGJd', 'input': {'query': 'LangGraph'}, 'name': 'tavily_search_results_json', 'type': 'tool_use'}]\n", + "[{'text': \"Okay, let's look into LangGraph for you. Here is a search for information on LangGraph:\", 'type': 'text'}, {'id': 'toolu_01CqY1etHc3VHbbhw3LyQqsw', 'input': {'query': 'LangGraph'}, 'name': 'tavily_search_results_json', 'type': 'tool_use'}]\n", "Tool Calls:\n", - " tavily_search_results_json (toolu_01DTyDpJ1kKdNps5yxv3AGJd)\n", - " Call ID: toolu_01DTyDpJ1kKdNps5yxv3AGJd\n", + " tavily_search_results_json (toolu_01CqY1etHc3VHbbhw3LyQqsw)\n", + " Call ID: toolu_01CqY1etHc3VHbbhw3LyQqsw\n", " Args:\n", " query: LangGraph\n" ] @@ -1618,7 +1659,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 36, "id": "6a44bedc-ea91-4c22-976c-98b3d5a5e4a7", "metadata": {}, "outputs": [ @@ -1632,7 +1673,7 @@ "\n", "\n", "Last 2 messages;\n", - "[ToolMessage(content='LangGraph is a library for building stateful, multi-actor applications with LLMs.', id='14589ef1-15db-4a75-82a6-d57c40a216d0', tool_call_id='toolu_01DTyDpJ1kKdNps5yxv3AGJd'), AIMessage(content='LangGraph is a library for building stateful, multi-actor applications with LLMs.', id='1c657bfb-7690-44c7-a26d-d0d22453013d')]\n" + "[ToolMessage(content='LangGraph is a library for building stateful, multi-actor applications with LLMs.', id='223dea92-6640-410c-aa43-bba0095fd78a', tool_call_id='toolu_01CqY1etHc3VHbbhw3LyQqsw'), AIMessage(content='LangGraph is a library for building stateful, multi-actor applications with LLMs.', id='9f22cfb8-bf27-4719-a993-c62a097dbb59')]\n" ] } ], @@ -1683,7 +1724,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 37, "id": "d16d95c3-b465-42ac-8015-26b669d45d1f", "metadata": {}, "outputs": [ @@ -1691,10 +1732,10 @@ "data": { "text/plain": [ "{'configurable': {'thread_id': '1',\n", - " 'thread_ts': '2024-05-06T22:27:57.350721+00:00'}}" + " 'thread_ts': '1ef4e869-e5ab-6fae-8003-4d3fa46aa0f6'}}" ] }, - "execution_count": 5, + "execution_count": 37, "metadata": {}, "output_type": "execute_result" } @@ -1719,13 +1760,13 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 38, "id": "f4009ba6-dc0b-4216-ab0c-fbb104616f73", "metadata": {}, "outputs": [ { "data": { - "image/jpeg": "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", + "image/jpeg": "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", "text/plain": [ "" ] @@ -1754,7 +1795,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 39, "id": "d420e813-a8c7-415d-ab31-5298d42491e4", "metadata": {}, "outputs": [ @@ -1762,7 +1803,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "[ToolMessage(content='LangGraph is a library for building stateful, multi-actor applications with LLMs.', id='14589ef1-15db-4a75-82a6-d57c40a216d0', tool_call_id='toolu_01DTyDpJ1kKdNps5yxv3AGJd'), AIMessage(content='LangGraph is a library for building stateful, multi-actor applications with LLMs.', id='1c657bfb-7690-44c7-a26d-d0d22453013d'), AIMessage(content=\"I'm an AI expert!\", id='acd668e3-ba31-42c0-843c-00d0994d5885')]\n", + "[ToolMessage(content='LangGraph is a library for building stateful, multi-actor applications with LLMs.', id='223dea92-6640-410c-aa43-bba0095fd78a', tool_call_id='toolu_01CqY1etHc3VHbbhw3LyQqsw'), AIMessage(content='LangGraph is a library for building stateful, multi-actor applications with LLMs.', id='9f22cfb8-bf27-4719-a993-c62a097dbb59'), AIMessage(content=\"I'm an AI expert!\", id='6bdec318-0cfc-4ed9-99f9-6b6541e209b1')]\n", "()\n" ] } @@ -1789,7 +1830,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 40, "id": "9fc99c7e-b61d-4aec-9c62-042798185ec3", "metadata": {}, "outputs": [ @@ -1802,10 +1843,10 @@ "I'm learning LangGraph. Could you do some research on it for me?\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "\n", - "[{'id': 'toolu_013MvjoDHnv476ZGzyPFZhrR', 'input': {'query': 'LangGraph'}, 'name': 'tavily_search_results_json', 'type': 'tool_use'}]\n", + "[{'text': \"Okay, let's look into LangGraph for you. \", 'type': 'text'}, {'id': 'toolu_01TjpejNNe4iV1pGLJn8PRXo', 'input': {'query': 'LangGraph'}, 'name': 'tavily_search_results_json', 'type': 'tool_use'}]\n", "Tool Calls:\n", - " tavily_search_results_json (toolu_013MvjoDHnv476ZGzyPFZhrR)\n", - " Call ID: toolu_013MvjoDHnv476ZGzyPFZhrR\n", + " tavily_search_results_json (toolu_01TjpejNNe4iV1pGLJn8PRXo)\n", + " Call ID: toolu_01TjpejNNe4iV1pGLJn8PRXo\n", " Args:\n", " query: LangGraph\n" ] @@ -1832,7 +1873,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 41, "id": "7215533a-b7e2-4b2d-bc1d-5122b1d06b8b", "metadata": {}, "outputs": [ @@ -1841,11 +1882,11 @@ "output_type": "stream", "text": [ "Original\n", - "Message ID run-59283969-1076-45fe-bee8-ebfccab163c3-0\n", - "{'name': 'tavily_search_results_json', 'args': {'query': 'LangGraph'}, 'id': 'toolu_013MvjoDHnv476ZGzyPFZhrR'}\n", + "Message ID run-e3756c3f-eaeb-4e3a-85ad-4977efbe3428-0\n", + "{'name': 'tavily_search_results_json', 'args': {'query': 'LangGraph'}, 'id': 'toolu_01TjpejNNe4iV1pGLJn8PRXo', 'type': 'tool_call'}\n", "Updated\n", - "{'name': 'tavily_search_results_json', 'args': {'query': 'LangGraph human-in-the-loop workflow'}, 'id': 'toolu_013MvjoDHnv476ZGzyPFZhrR'}\n", - "Message ID run-59283969-1076-45fe-bee8-ebfccab163c3-0\n", + "{'name': 'tavily_search_results_json', 'args': {'query': 'LangGraph human-in-the-loop workflow'}, 'id': 'toolu_01TjpejNNe4iV1pGLJn8PRXo', 'type': 'tool_call'}\n", + "Message ID run-e3756c3f-eaeb-4e3a-85ad-4977efbe3428-0\n", "\n", "\n", "Tool calls\n" @@ -1856,10 +1897,11 @@ "text/plain": [ "[{'name': 'tavily_search_results_json',\n", " 'args': {'query': 'LangGraph human-in-the-loop workflow'},\n", - " 'id': 'toolu_013MvjoDHnv476ZGzyPFZhrR'}]" + " 'id': 'toolu_01TjpejNNe4iV1pGLJn8PRXo',\n", + " 'type': 'tool_call'}]" ] }, - "execution_count": 9, + "execution_count": 41, "metadata": {}, "output_type": "execute_result" } @@ -1904,7 +1946,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 42, "id": "03a09bfc-3d90-4e54-878f-22e3cb28a418", "metadata": {}, "outputs": [ @@ -1915,16 +1957,17 @@ "=================================\u001b[1m Tool Message \u001b[0m=================================\n", "Name: tavily_search_results_json\n", "\n", - "[{\"url\": \"https://langchain-ai.github.io/langgraph/how-tos/human-in-the-loop/\", \"content\": \"Human-in-the-loop\\u00b6 When creating LangGraph agents, it is often nice to add a human in the loop component. This can be helpful when giving them access to tools. ... 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) ...\"}, {\"url\": \"https://langchain-ai.github.io/langgraph/how-tos/chat_agent_executor_with_function_calling/human-in-the-loop/\", \"content\": \"Human-in-the-loop. In this example we will build a ReAct Agent that has a human in the loop. We will use the human to approve specific actions. This examples builds off the base chat executor. It is highly recommended you learn about that executor before going through this notebook. You can find documentation for that example here.\"}]\n", + "[{\"url\": \"https://www.youtube.com/watch?v=9BPCV5TYPmg\", \"content\": \"In this video, I'll show you how to handle persistence with LangGraph, enabling a unique Human-in-the-Loop workflow. This approach allows a human to grant an LLM (Language Model) permission to ...\"}, {\"url\": \"https://github.com/langchain-ai/langgraph\", \"content\": \"As a very low-level framework, it provides fine-grained control over both the flow and state of your application, crucial for creating reliable agents. Additionally, LangGraph includes built-in persistence, enabling advanced human-in-the-loop and memory features. LangGraph is inspired by Pregel and Apache Beam.\"}]\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "\n", - "Based on the search results, LangGraph appears to be a framework for building AI agents that can interact with humans in a conversational way. The key points I gathered are:\n", + "Based on the search results, a few key things to note about LangGraph:\n", "\n", - "- LangGraph allows for \"human-in-the-loop\" workflows, where a human can be involved in approving or reviewing actions taken by the AI agent.\n", - "- This can be useful for giving the AI agent access to various tools and capabilities, with the human able to provide oversight and guidance.\n", - "- The framework includes components like \"MessageGraph\" for defining the conversational flow between the agent and human.\n", + "- It is a low-level framework that provides fine-grained control over the flow and state of AI applications, including language models.\n", + "- LangGraph includes built-in persistence and memory features, which enable advanced human-in-the-loop workflows.\n", + "- The human-in-the-loop aspect allows a human to grant permissions and interact with the language model in the application.\n", + "- LangGraph is inspired by frameworks like Pregel and Apache Beam, which are used for large-scale distributed graph processing.\n", "\n", - "Overall, LangGraph seems to be a way to create conversational AI agents that can leverage human input and guidance, rather than operating in a fully autonomous way. Let me know if you need any clarification or have additional questions!\n" + "So in summary, LangGraph seems to be a framework that allows developers to build reliable AI agents with persistent memory and seamless human-in-the-loop interaction. The low-level control it provides is useful for creating complex, production-ready AI applications. Let me know if you need any clarification or have additional questions!\n" ] } ], @@ -1947,7 +1990,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 43, "id": "11d5b934-6d8b-4f52-a3bc-b3daa7207e00", "metadata": {}, "outputs": [ @@ -1960,11 +2003,12 @@ "Remember what I'm learning about?\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "\n", - "Ah yes, now I remember - you mentioned earlier that you are learning about LangGraph.\n", - "\n", - "LangGraph is the framework I researched in my previous response, which is for building conversational AI agents that can incorporate human input and oversight.\n", - "\n", - "So based on our earlier discussion, it seems you are currently learning about and exploring the LangGraph system for creating human-in-the-loop AI agents. Please let me know if I have the right understanding now.\n" + "[{'text': \"Ah, got it - you mentioned you're learning about LangGraph, so that's what we should focus on. Let me do some more targeted research on that:\", 'type': 'text'}, {'id': 'toolu_01VtBZ6g6TB7Y1ggLhAuWQc1', 'input': {'query': 'what is langraph'}, 'name': 'tavily_search_results_json', 'type': 'tool_use'}]\n", + "Tool Calls:\n", + " tavily_search_results_json (toolu_01VtBZ6g6TB7Y1ggLhAuWQc1)\n", + " Call ID: toolu_01VtBZ6g6TB7Y1ggLhAuWQc1\n", + " Args:\n", + " query: what is langraph\n" ] } ], @@ -2012,7 +2056,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 44, "id": "3cf7e042-1718-4625-ae30-a9917f595449", "metadata": {}, "outputs": [], @@ -2046,7 +2090,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 45, "id": "e5192e54-6a28-42fe-a8a7-62d45d61f994", "metadata": {}, "outputs": [], @@ -2073,19 +2117,10 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 46, "id": "fa59b266-14e5-4c75-8b3d-54fac28e8290", "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/wfh/code/lc/langchain/libs/core/langchain_core/_api/beta_decorator.py:87: LangChainBetaWarning: The method `ChatAnthropic.bind_tools` is in beta. It is actively being worked on, so the API may change.\n", - " warn_beta(\n" - ] - } - ], + "outputs": [], "source": [ "tool = TavilySearchResults(max_results=2)\n", "tools = [tool]\n", @@ -2115,7 +2150,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 47, "id": "3f4464d2-288b-4689-aaf0-329a55dcb85c", "metadata": {}, "outputs": [], @@ -2136,7 +2171,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 48, "id": "1d70b5a4-ce50-47dc-aa43-ffb5c48c46fc", "metadata": {}, "outputs": [], @@ -2183,7 +2218,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 49, "id": "586a0d07-8303-47f4-b3cf-3bdd043e762b", "metadata": {}, "outputs": [], @@ -2212,7 +2247,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 50, "id": "84101737-0048-4635-9f68-45b0c508b6b6", "metadata": {}, "outputs": [], @@ -2239,13 +2274,13 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 51, "id": "b3220ae2-cba0-4447-96d1-eb0be4684e59", "metadata": {}, "outputs": [ { "data": { - "image/jpeg": "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", + "image/jpeg": "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", "text/plain": [ "" ] @@ -2276,7 +2311,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 52, "id": "c1955d79-a1e4-47d0-ba79-b45bd5752a23", "metadata": {}, "outputs": [ @@ -2289,10 +2324,10 @@ "I need some expert guidance for building this AI agent. Could you request assistance for me?\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "\n", - "[{'id': 'toolu_017XaQuVsoAyfXeTfDyv55Pc', 'input': {'request': 'I need some expert guidance for building this AI agent.'}, 'name': 'RequestAssistance', 'type': 'tool_use'}]\n", + "[{'id': 'toolu_01N2gu7Bi5bcG4ZMBpgDpjLT', 'input': {'request': 'I need some expert guidance for building this AI agent.'}, 'name': 'RequestAssistance', 'type': 'tool_use'}]\n", "Tool Calls:\n", - " RequestAssistance (toolu_017XaQuVsoAyfXeTfDyv55Pc)\n", - " Call ID: toolu_017XaQuVsoAyfXeTfDyv55Pc\n", + " RequestAssistance (toolu_01N2gu7Bi5bcG4ZMBpgDpjLT)\n", + " Call ID: toolu_01N2gu7Bi5bcG4ZMBpgDpjLT\n", " Args:\n", " request: I need some expert guidance for building this AI agent.\n" ] @@ -2320,7 +2355,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 53, "id": "5320ba05-5696-4194-8278-5385c571264d", "metadata": {}, "outputs": [ @@ -2330,7 +2365,7 @@ "('human',)" ] }, - "execution_count": 10, + "execution_count": 53, "metadata": {}, "output_type": "execute_result" } @@ -2354,7 +2389,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 54, "id": "2cbac924-61ce-4282-9b1c-77f9090ea1f5", "metadata": {}, "outputs": [ @@ -2362,10 +2397,10 @@ "data": { "text/plain": [ "{'configurable': {'thread_id': '1',\n", - " 'thread_ts': '2024-05-06T22:31:39.973392+00:00'}}" + " 'thread_ts': '1ef4e86c-346b-6e12-8002-29df0f635b61'}}" ] }, - "execution_count": 11, + "execution_count": 54, "metadata": {}, "output_type": "execute_result" } @@ -2390,19 +2425,19 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 55, "id": "4b986c66-1c65-4da8-a404-db7e28f8364e", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "[HumanMessage(content='I need some expert guidance for building this AI agent. Could you request assistance for me?', id='ab75eb9d-cce7-4e44-8de7-b0b375a86972'),\n", - " AIMessage(content=[{'id': 'toolu_017XaQuVsoAyfXeTfDyv55Pc', 'input': {'request': 'I need some expert guidance for building this AI agent.'}, 'name': 'RequestAssistance', 'type': 'tool_use'}], response_metadata={'id': 'msg_0199PiK6kmVAbeo1qmephKDq', 'model': 'claude-3-haiku-20240307', 'stop_reason': 'tool_use', 'stop_sequence': None, 'usage': {'input_tokens': 486, 'output_tokens': 63}}, id='run-ff07f108-5055-4343-8910-2fa40ead3fb9-0', tool_calls=[{'name': 'RequestAssistance', 'args': {'request': 'I need some expert guidance for building this AI agent.'}, 'id': 'toolu_017XaQuVsoAyfXeTfDyv55Pc'}]),\n", - " ToolMessage(content=\"We, the experts are here to help! We'd recommend you check out LangGraph to build your agent. It's much more reliable and extensible than simple autonomous agents.\", id='19f2eb9f-a742-46aa-9047-60909c30e64a', tool_call_id='toolu_017XaQuVsoAyfXeTfDyv55Pc')]" + "[HumanMessage(content='I need some expert guidance for building this AI agent. Could you request assistance for me?', id='0e6f70a1-2eb7-4147-9f1b-2916945a4464'),\n", + " AIMessage(content=[{'id': 'toolu_01N2gu7Bi5bcG4ZMBpgDpjLT', 'input': {'request': 'I need some expert guidance for building this AI agent.'}, 'name': 'RequestAssistance', 'type': 'tool_use'}], response_metadata={'id': 'msg_01Hs1eHtNi4W2sT1S579K9wn', 'model': 'claude-3-haiku-20240307', 'stop_reason': 'tool_use', 'stop_sequence': None, 'usage': {'input_tokens': 486, 'output_tokens': 63}}, id='run-ec298c8a-6cb6-4f8c-8a4e-dde475465464-0', tool_calls=[{'name': 'RequestAssistance', 'args': {'request': 'I need some expert guidance for building this AI agent.'}, 'id': 'toolu_01N2gu7Bi5bcG4ZMBpgDpjLT', 'type': 'tool_call'}], usage_metadata={'input_tokens': 486, 'output_tokens': 63, 'total_tokens': 549}),\n", + " ToolMessage(content=\"We, the experts are here to help! We'd recommend you check out LangGraph to build your agent. It's much more reliable and extensible than simple autonomous agents.\", id='1e95a954-c149-4d70-b660-b6da028434b1', tool_call_id='toolu_01N2gu7Bi5bcG4ZMBpgDpjLT')]" ] }, - "execution_count": 12, + "execution_count": 55, "metadata": {}, "output_type": "execute_result" } @@ -2421,7 +2456,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 56, "id": "6b32914d-4d60-491f-8e11-1e6867e38ffd", "metadata": {}, "outputs": [ @@ -2434,7 +2469,7 @@ "We, the experts are here to help! We'd recommend you check out LangGraph to build your agent. It's much more reliable and extensible than simple autonomous agents.\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "\n", - "It looks like the experts have provided some guidance on how to build your AI agent. They suggested checking out LangGraph, which they say is more reliable and extensible than simple autonomous agents. Please let me know if you need any other assistance - I'm happy to help coordinate with the expert team further.\n" + "It looks like the experts have provided some guidance for building your AI agent. They recommended using LangGraph, which they say is a more reliable and extensible solution compared to simple autonomous agents. Please let me know if you need any clarification or have additional questions!\n" ] } ], @@ -2588,7 +2623,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 57, "id": "bb8a02de-a21b-4ef6-a714-7d6e44435e3a", "metadata": {}, "outputs": [], @@ -2697,13 +2732,13 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 58, "id": "a7debb4a-2a3a-40b9-a48c-7052ec2c2726", "metadata": {}, "outputs": [ { "data": { - "image/jpeg": "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", + "image/jpeg": "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", "text/plain": [ "" ] @@ -2732,7 +2767,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 59, "id": "69071b02-c011-4b7f-90b1-8e89e032322d", "metadata": {}, "outputs": [ @@ -2745,31 +2780,31 @@ "I'm learning LangGraph. Could you do some research on it for me?\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "\n", - "[{'text': \"Okay, let me look into LangGraph for you. Here's what I found:\", 'type': 'text'}, {'id': 'toolu_011AQ2FT4RupVka2LVMV3Gci', 'input': {'query': 'LangGraph'}, 'name': 'tavily_search_results_json', 'type': 'tool_use'}]\n", + "[{'id': 'toolu_01THWXM2rGdKZk7k75RtVpse', 'input': {'query': 'LangGraph'}, 'name': 'tavily_search_results_json', 'type': 'tool_use'}]\n", "Tool Calls:\n", - " tavily_search_results_json (toolu_011AQ2FT4RupVka2LVMV3Gci)\n", - " Call ID: toolu_011AQ2FT4RupVka2LVMV3Gci\n", + " tavily_search_results_json (toolu_01THWXM2rGdKZk7k75RtVpse)\n", + " Call ID: toolu_01THWXM2rGdKZk7k75RtVpse\n", " Args:\n", " query: LangGraph\n", "=================================\u001b[1m Tool Message \u001b[0m=================================\n", "Name: tavily_search_results_json\n", "\n", - "[{\"url\": \"https://langchain-ai.github.io/langgraph/\", \"content\": \"LangGraph is framework agnostic (each node is a regular python function). It extends the core Runnable API (shared interface for streaming, async, and batch calls) to make it easy to: Seamless state management across multiple turns of conversation or tool usage. The ability to flexibly route between nodes based on dynamic criteria.\"}, {\"url\": \"https://blog.langchain.dev/langgraph-multi-agent-workflows/\", \"content\": \"As a part of the launch, we highlighted two simple runtimes: one that is the equivalent of the AgentExecutor in langchain, and a second that was a version of that aimed at message passing and chat models.\\n It's important to note that these three examples are only a few of the possible examples we could highlight - there are almost assuredly other examples out there and we look forward to seeing what the community comes up with!\\n LangGraph: Multi-Agent Workflows\\nLinks\\nLast week we highlighted LangGraph - a new package (available in both Python and JS) to better enable creation of LLM workflows containing cycles, which are a critical component of most agent runtimes. \\\"\\nAnother key difference between Autogen and LangGraph is that LangGraph is fully integrated into the LangChain ecosystem, meaning you take fully advantage of all the LangChain integrations and LangSmith observability.\\n As part of this launch, we're also excited to highlight a few applications built on top of LangGraph that utilize the concept of multiple agents.\\n\"}]\n", + "[{\"url\": \"https://blog.langchain.dev/langgraph-cloud/\", \"content\": \"LangGraph is a framework for building agentic and multi-agent applications with LLMs, and LangGraph Cloud is a scalable and reliable infrastructure for deploying them. Learn how LangGraph helps you design, debug, and monitor complex agentic workflows with LLMs.\"}, {\"url\": \"https://langchain-ai.github.io/langgraph/tutorials/\", \"content\": \"LangGraph is a framework for building language agents as graphs. Learn how to use LangGraph to create chatbots, code assistants, planning agents, reflection agents, and more with these notebooks.\"}]\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "\n", - "Based on the search results, here's what I've learned about LangGraph:\n", + "Based on the search results, LangGraph appears to be a framework for building applications and agents that utilize large language models (LLMs). It provides a way to design, debug, and monitor complex workflows and interactions between multiple language-based agents.\n", "\n", - "- LangGraph is a framework-agnostic tool that extends the Runnable API to make it easier to manage state and routing between different nodes or agents in a conversational workflow. \n", + "The key things I've learned about LangGraph:\n", "\n", - "- It's part of the LangChain ecosystem, so it integrates with other LangChain tools and observability features.\n", + "- It is a framework for building \"agentic and multi-agent applications\" with LLMs. This allows you to create more sophisticated applications that involve multiple interacting agents, rather than just a single language model.\n", "\n", - "- LangGraph enables the creation of multi-agent workflows, where you can have different \"nodes\" or agents that can communicate and pass information to each other.\n", + "- LangGraph Cloud is the scalable infrastructure for deploying these LangGraph-based applications.\n", "\n", - "- This allows for more complex conversational flows and the ability to chain together different capabilities, tools, or models.\n", + "- It provides tutorials and examples for building various types of agents with LangGraph, including chatbots, code assistants, planning agents, and more.\n", "\n", - "- The key benefits seem to be around state management, flexible routing between agents, and the ability to create more sophisticated and dynamic conversational workflows.\n", + "- The goal is to enable the development of more complex, interactive, and intelligent applications powered by large language models.\n", "\n", - "Let me know if you need any clarification or have additional questions! I'm happy to do more research on LangGraph if you need further details.\n" + "Overall, LangGraph seems to be an interesting and powerful framework for leveraging LLMs in more sophisticated ways beyond just a single-agent chatbot or question answering system. Let me know if you have any other questions about it!\n" ] } ], @@ -2791,7 +2826,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 60, "id": "acbec099-e5d2-497f-929e-c548d7bcbf77", "metadata": {}, "outputs": [ @@ -2804,31 +2839,29 @@ "Ya that's helpful. Maybe I'll build an autonomous agent with it!\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "\n", - "[{'text': \"That's great that you're interested in building an autonomous agent using LangGraph! Here are a few additional thoughts on how you could approach that:\", 'type': 'text'}, {'id': 'toolu_01L3V9FhZG5Qx9jqRGfWGtS2', 'input': {'query': 'building autonomous agents with langgraph'}, 'name': 'tavily_search_results_json', 'type': 'tool_use'}]\n", + "[{'text': \"That's great that you're interested in building an autonomous agent using LangGraph! Here are a few additional thoughts on that:\", 'type': 'text'}, {'id': 'toolu_01DjiDfFLusrTqEqpRDF5Dav', 'input': {'query': 'building autonomous agents with LangGraph'}, 'name': 'tavily_search_results_json', 'type': 'tool_use'}]\n", "Tool Calls:\n", - " tavily_search_results_json (toolu_01L3V9FhZG5Qx9jqRGfWGtS2)\n", - " Call ID: toolu_01L3V9FhZG5Qx9jqRGfWGtS2\n", + " tavily_search_results_json (toolu_01DjiDfFLusrTqEqpRDF5Dav)\n", + " Call ID: toolu_01DjiDfFLusrTqEqpRDF5Dav\n", " Args:\n", - " query: building autonomous agents with langgraph\n", + " query: building autonomous agents with LangGraph\n", "=================================\u001b[1m Tool Message \u001b[0m=================================\n", "Name: tavily_search_results_json\n", "\n", - "[{\"url\": \"https://github.com/langchain-ai/langgraphjs\", \"content\": \"LangGraph is a library for building stateful, multi-actor applications with LLMs, built on top of (and intended to be used with) LangChain.js.It extends the LangChain Expression Language with the ability to coordinate multiple chains (or actors) across multiple steps of computation in a cyclic manner. It is inspired by Pregel and Apache Beam.The current interface exposed is one inspired by ...\"}, {\"url\": \"https://github.com/langchain-ai/langgraph\", \"content\": \"LangGraph is a library for building stateful, multi-actor applications with LLMs. It extends the LangChain Expression Language with the ability to coordinate multiple chains (or actors) across multiple steps of computation in a cyclic manner. It is inspired by Pregel and Apache Beam.The current interface exposed is one inspired by NetworkX.. The main use is for adding cycles to your LLM ...\"}]\n", + "[{\"url\": \"https://blog.langchain.dev/how-to-build-the-ultimate-ai-automation-with-multi-agent-collaboration/\", \"content\": \"In this blog, he walks through how to build an autonomous research assistant using LangGraph with a team of specialized agents. It has only been a year since the initial release of GPT Researcher, but methods for building, testing, and deploying AI agents have already evolved significantly. That's just the nature and speed of the current AI ...\"}, {\"url\": \"https://blog.paperspace.com/building-local-ai-agents-a-guide-to-langgraph-ai-agents-and-ollama/\", \"content\": \"In summary, the integration of LangGraph and Ollama provides a robust framework for building AI agents that are both effective and efficient. This guide is a valuable resource for anyone looking to harness the potential of these technologies to drive innovation and achieve their objectives in the ever-evolving landscape of artificial intelligence.\"}]\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "\n", - "The key things to keep in mind:\n", - "\n", - "1. LangGraph is designed to help coordinate multiple \"agents\" or \"actors\" that can pass information back and forth. This allows you to build more complex, multi-step workflows.\n", + "The key things I gathered about building autonomous agents with LangGraph:\n", "\n", - "2. You'll likely want to define different nodes or agents that handle specific tasks or capabilities. LangGraph makes it easy to route between these agents based on the state of the conversation.\n", + "- LangGraph enables you to create a \"team\" or network of specialized agents that can collaborate to accomplish complex tasks. This could allow you to build a very sophisticated autonomous agent system.\n", "\n", - "3. Make sure to leverage the LangChain ecosystem - things like prompts, memory, agents, tools etc. LangGraph integrates with these to give you a powerful set of building blocks.\n", + "- The blog post on building an \"ultimate AI automation\" with multi-agent collaboration provides a good example of how to do this. It walks through building an autonomous research assistant agent using LangGraph.\n", "\n", - "4. Pay close attention to state management - LangGraph helps you manage state across multiple interactions, which is crucial for an autonomous agent.\n", + "- Another blog post highlights how LangGraph can be integrated with the Ollama framework to build efficient and effective local AI agents.\n", "\n", - "5. Consider how you'll handle things like user intent, context, and goal-driven behavior. LangGraph gives you the flexibility to implement these kinds of complex behaviors.\n", + "So in summary, LangGraph seems very well-suited for building complex, autonomous agent systems by allowing you to compose multiple specialized agents into a cohesive whole. The tutorials and examples available should provide a great starting point as you explore building your own autonomous agent with LangGraph.\n", "\n", - "Let me know if you have any other specific questions as you start prototyping your autonomous agent! I'm happy to provide more guidance.\n" + "Let me know if you have any other questions! I'm happy to continue researching this topic to support your learning and development work.\n" ] } ], @@ -2857,7 +2890,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 61, "id": "6c0dbed5-210d-40ad-b002-0bc52ef28fac", "metadata": {}, "outputs": [ @@ -2869,17 +2902,21 @@ "--------------------------------------------------------------------------------\n", "Num Messages: 7 Next: ('chatbot',)\n", "--------------------------------------------------------------------------------\n", - "Num Messages: 6 Next: ('action',)\n", + "Num Messages: 6 Next: ('tools',)\n", "--------------------------------------------------------------------------------\n", "Num Messages: 5 Next: ('chatbot',)\n", "--------------------------------------------------------------------------------\n", + "Num Messages: 4 Next: ('__start__',)\n", + "--------------------------------------------------------------------------------\n", "Num Messages: 4 Next: ()\n", "--------------------------------------------------------------------------------\n", "Num Messages: 3 Next: ('chatbot',)\n", "--------------------------------------------------------------------------------\n", - "Num Messages: 2 Next: ('action',)\n", + "Num Messages: 2 Next: ('tools',)\n", "--------------------------------------------------------------------------------\n", "Num Messages: 1 Next: ('chatbot',)\n", + "--------------------------------------------------------------------------------\n", + "Num Messages: 0 Next: ('__start__',)\n", "--------------------------------------------------------------------------------\n" ] } @@ -2906,7 +2943,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 62, "id": "de8d5521-8d71-4093-a657-4920c790802f", "metadata": {}, "outputs": [ @@ -2914,8 +2951,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "('action',)\n", - "{'configurable': {'thread_id': '1', 'thread_ts': '2024-05-06T22:33:10.211424+00:00'}}\n" + "('tools',)\n", + "{'configurable': {'thread_id': '1', 'thread_ts': '1ef4e86c-f05f-6e20-8006-9868145c4336'}}\n" ] } ], @@ -2934,7 +2971,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 63, "id": "85f17be3-eaf6-495e-a846-49436916b4ab", "metadata": {}, "outputs": [ @@ -2945,26 +2982,20 @@ "=================================\u001b[1m Tool Message \u001b[0m=================================\n", "Name: tavily_search_results_json\n", "\n", - "[{\"url\": \"https://valentinaalto.medium.com/getting-started-with-langgraph-66388e023754\", \"content\": \"Sign up\\nSign in\\nSign up\\nSign in\\nMember-only story\\nGetting Started with LangGraph\\nBuilding multi-agents application with graph frameworks\\nValentina Alto\\nFollow\\n--\\nShare\\nOver the last year, LangChain has established itself as one of the most popular AI framework available in the market. This new library, introduced in January\\u2026\\n--\\n--\\nWritten by Valentina Alto\\nData&AI Specialist at @Microsoft | MSc in Data Science | AI, Machine Learning and Running enthusiast\\nHelp\\nStatus\\nAbout\\nCareers\\nBlog\\nPrivacy\\nTerms\\nText to speech\\nTeams Since the concept of multi-agent applications \\u2014 the ones exhibiting different agents, each having a specific personality and tools to access \\u2014 is getting real and mainstream (see the rise of libraries projects like AutoGen), LangChain\\u2019s developers introduced a new library to make it easier to manage these kind of agentic applications. Nevertheless, those chains were lacking the capability of introducing cycles into their runtime, meaning that there is no out-of-the-box framework to enable the LLM to reason over the next best action in a kind of for-loop scenario. The main feature of LangChain \\u2014 as the name suggests \\u2014 is its ability to easily create the so-called chains.\"}, {\"url\": \"https://blog.langchain.dev/langgraph-multi-agent-workflows/\", \"content\": \"As a part of the launch, we highlighted two simple runtimes: one that is the equivalent of the AgentExecutor in langchain, and a second that was a version of that aimed at message passing and chat models.\\n It's important to note that these three examples are only a few of the possible examples we could highlight - there are almost assuredly other examples out there and we look forward to seeing what the community comes up with!\\n LangGraph: Multi-Agent Workflows\\nLinks\\nLast week we highlighted LangGraph - a new package (available in both Python and JS) to better enable creation of LLM workflows containing cycles, which are a critical component of most agent runtimes. \\\"\\nAnother key difference between Autogen and LangGraph is that LangGraph is fully integrated into the LangChain ecosystem, meaning you take fully advantage of all the LangChain integrations and LangSmith observability.\\n As part of this launch, we're also excited to highlight a few applications built on top of LangGraph that utilize the concept of multiple agents.\\n\"}]\n", + "[{\"url\": \"https://blog.langchain.dev/how-to-build-the-ultimate-ai-automation-with-multi-agent-collaboration/\", \"content\": \"In this blog, he walks through how to build an autonomous research assistant using LangGraph with a team of specialized agents. It has only been a year since the initial release of GPT Researcher, but methods for building, testing, and deploying AI agents have already evolved significantly. That's just the nature and speed of the current AI ...\"}, {\"url\": \"https://blog.paperspace.com/building-local-ai-agents-a-guide-to-langgraph-ai-agents-and-ollama/\", \"content\": \"In summary, the integration of LangGraph and Ollama provides a robust framework for building AI agents that are both effective and efficient. This guide is a valuable resource for anyone looking to harness the potential of these technologies to drive innovation and achieve their objectives in the ever-evolving landscape of artificial intelligence.\"}]\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "\n", - "The key things I gathered are:\n", - "\n", - "- LangGraph is well-suited for building multi-agent applications, where you have different agents with their own capabilities, tools, and personality.\n", + "The search results provide some helpful guidance on using LangGraph to build autonomous agents:\n", "\n", - "- It allows you to create more complex workflows with cycles and feedback loops, which is critical for building autonomous agents that can reason about their next best actions.\n", + "- LangGraph allows you to create a \"team\" of specialized agents that can collaborate together to accomplish complex tasks. This could be useful for building a versatile autonomous assistant.\n", "\n", - "- The integration with LangChain means you can leverage other useful features like state management, observability, and integrations with various language models and data sources.\n", + "- There are techniques for designing, testing, and deploying these multi-agent AI systems using LangGraph and complementary tools like Ollama.\n", "\n", - "Some tips for building an autonomous agent with LangGraph:\n", + "- The tutorials and examples show how to leverage LangGraph to build agents for different use cases like research, automation, and more.\n", "\n", - "1. Define the different agents/nodes in your workflow and their specific responsibilities/capabilities.\n", - "2. Set up the connections and routing between the agents so they can pass information and decisions back and forth.\n", - "3. Implement logic within each agent to assess the current state and determine the optimal next action.\n", - "4. Use LangChain features like memory and toolkits to give your agents access to relevant information and abilities.\n", - "5. Monitor the overall system behavior and iteratively improve the agent interactions and decision-making.\n", + "The key seems to be leveraging LangGraph's ability to coordinate multiple agents with distinct capabilities. This could allow you to build a very capable and adaptable autonomous system. Just be sure to carefully design the interactions and decision-making between the agents.\n", "\n", - "Let me know if you have any other questions! I'm happy to provide more guidance as you start building your autonomous agent with LangGraph.\n" + "Let me know if you have any other questions as you start exploring LangGraph for your autonomous agent project! I'm happy to provide more insights.\n" ] } ], @@ -2996,6 +3027,14 @@ "\n", "The [LangGraph documentation](https://langchain-ai.github.io/langgraph/) is a great resource for diving deeper into the library's capabilities." ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "31a052c7-e8f2-4f95-a764-2183f4649343", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/langchain_vids/agent_executor.ipynb b/langchain_vids/agent_executor.ipynb new file mode 100644 index 0000000..e42bd13 --- /dev/null +++ b/langchain_vids/agent_executor.ipynb @@ -0,0 +1,290 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "d92bf399-f5a1-4df3-b69f-61ea56f25b5a", + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "import os\n", + "\n", + "# Get the directory of the current notebook\n", + "current_dir = os.path.dirname(os.path.abspath('__file__'))\n", + "\n", + "# Move up to the root directory\n", + "root_dir = os.path.abspath(os.path.join(current_dir, '..'))\n", + "\n", + "# Add the root directory to the sys.path\n", + "sys.path.append(root_dir)\n", + "\n", + "from graph_gen.gen_graph import gen_graph\n", + "from langchain_community.tools.tavily_search import TavilySearchResults\n", + "from langchain import hub\n", + "from langchain_openai.chat_models import ChatOpenAI\n", + "from langchain.agents import create_openai_functions_agent\n", + "from langgraph.prebuilt.tool_executor import ToolExecutor\n", + "from typing import Annotated, Dict, List, Optional, TypedDict, Tuple, Sequence, Union, Literal\n", + "from langchain_core.messages import AIMessage, BaseMessage, FunctionMessage, HumanMessage, ToolMessage\n", + "from langgraph.graph import END, StateGraph, MessageGraph\n", + "from langchain_core.agents import AgentAction, AgentFinish\n", + "from langchain.output_parsers.openai_tools import (\n", + " JsonOutputToolsParser,\n", + " PydanticToolsParser\n", + ")\n", + "from langchain.agents.output_parsers.openai_functions import OpenAIFunctionsAgentOutputParser\n", + "import operator\n", + "import re" + ] + }, + { + "cell_type": "markdown", + "id": "4d10e7e8-4427-4485-8f3b-160ac13e8f94", + "metadata": {}, + "source": [ + "### [LangGraph: Agent Executor](https://www.youtube.com/watch?v=9dXp5q3OFdQ&list=PLfaIDFEXuae16n2TWUkKq5PgJ0w6Pkwtg&index=2) \"YouTube\"" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "8e0a3de7-10eb-4d1c-9931-d40439f7c9f5", + "metadata": {}, + "outputs": [], + "source": [ + "# State\n", + "class AgentState(TypedDict):\n", + " input: str\n", + " chat_history: List[BaseMessage]\n", + " agent_outcome: Union[AgentAction, AgentFinish, None]\n", + " agent_scratchpad: List[object]\n", + " intermediate_steps: Annotated[list[tuple[AgentAction, str]], operator.add]" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "bc414185-0092-46ee-9632-db8c558d4ede", + "metadata": {}, + "outputs": [], + "source": [ + "# Nodes\n", + "def agent(state):\n", + " agent_outcome = agent_runnable.invoke(state)\n", + " return { \"agent_outcome\": agent_outcome }\n", + "\n", + "def action(state):\n", + " agent_action = state['agent_outcome']\n", + " output = tool_executor.invoke(agent_action)\n", + " return { \"intermediate_steps\": [(agent_action, str(output))] }" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "98371e68-993c-47c9-a844-dc69b91967b0", + "metadata": {}, + "outputs": [], + "source": [ + "# Tools\n", + "tools = [TavilySearchResults(max_results=1)]\n", + "prompt = hub.pull(\"hwchase17/openai-functions-agent\")\n", + "llm = ChatOpenAI(model=\"gpt-4o\", streaming=True)\n", + "agent_runnable = prompt | llm.bind_tools(tools) | OpenAIFunctionsAgentOutputParser()\n", + "tool_executor = ToolExecutor(tools)\n", + "\n", + "def print_result(s):\n", + " if 'agent' in s and 'agent_outcome' in s['agent'] and isinstance(s['agent']['agent_outcome'], AgentFinish):\n", + " print(s['agent']['agent_outcome'].return_values['output'])\n", + " else:\n", + " print(s)\n", + " print()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "b4843cef-ed0d-4ff8-bb60-d0c73d4550d0", + "metadata": {}, + "outputs": [], + "source": [ + "# Nodes\n", + "def init(state):\n", + " return { \"chat_history\": [], \"agent_outcome\": None, \"agent_scratchpad\": [] }\n", + " \n", + "# Graph\n", + "graph_spec = \"\"\"\n", + "\n", + "init(AgentState)\n", + " => agent\n", + " \n", + "agent\n", + " is_finished => END\n", + " => action\n", + "\n", + "action\n", + " => agent\n", + "\n", + "\"\"\"\n", + "\n", + "# Conditional edges\n", + "def is_finished(state):\n", + " return isinstance(state['agent_outcome'], AgentFinish)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "18485010-08b0-4b9f-86ce-3809d933c6ba", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "agent_exec = StateGraph(AgentState)\n", + "agent_exec.add_node('init', init)\n", + "agent_exec.add_node('agent', agent)\n", + "agent_exec.add_node('action', action)\n", + "\n", + "agent_exec.set_entry_point('init')\n", + "\n", + "agent_exec.add_edge('init', 'agent')\n", + "def after_agent(state: AgentState):\n", + " if is_finished(state):\n", + " return 'END'\n", + " return 'action'\n", + "\n", + "agent_dict = {'END': END, 'action': 'action'}\n", + "agent_exec.add_conditional_edges('agent', after_agent, agent_dict)\n", + "\n", + "agent_exec.add_edge('action', 'agent')\n", + "\n", + "agent_exec = agent_exec.compile()\n" + ] + } + ], + "source": [ + "# Run the graph\n", + "# - generate the python langgraph code\n", + "# - execute the code, runnable graph in variable 'app'\n", + "# - test the graph\n", + "graph_code = gen_graph(\"agent_exec\", graph_spec)\n", + "print(graph_code)\n", + "exec(graph_code)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "67c8022d-ebe8-45a6-9a7e-99382f1c2132", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'init': {'chat_history': [], 'agent_outcome': None, 'agent_scratchpad': []}}\n", + "\n", + "\n", + "\n", + "RESULT1 {'input': 'who is a female voice actress who does animal voices', 'chat_history': [], 'agent_outcome': AgentFinish(return_values={'output': ''}, log=''), 'agent_scratchpad': [], 'intermediate_steps': []}\n", + "RESULT2 {'input': 'who is a female voice actress who does animal voices', 'chat_history': [], 'agent_outcome': AgentFinish(return_values={'output': ''}, log=''), 'agent_scratchpad': [], 'intermediate_steps': []}\n" + ] + } + ], + "source": [ + "# Another test\n", + "inputs = { \"input\": \"who is a female voice actress who does animal voices\", \"chat_history\": [], \"agent_scratchpad\": [] }\n", + "for s in agent_exec.stream(inputs):\n", + " print_result(s)\n", + "inputs = { \"input\": \"who is a female voice actress who does animal voices\", \"chat_history\": [], \"agent_scratchpad\": [] }\n", + "result1 = agent_exec.invoke(inputs)\n", + "print(\"RESULT1\", result1)\n", + "inputs = { \"input\": \"who is a female voice actress who does animal voices\", \"agent_scratchpad\": [] }\n", + "result2 = agent_exec.invoke(inputs)\n", + "print(\"RESULT2\", result2)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "6be2ec4f-e0b7-4567-850b-e8bc3ad77235", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'input': 'who is a female voice actress who does animal voices',\n", + " 'chat_history': [],\n", + " 'agent_outcome': AgentFinish(return_values={'output': ''}, log=''),\n", + " 'agent_scratchpad': [],\n", + " 'intermediate_steps': []}" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "result1" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "2b2fdd67-5497-43d4-b202-4ba0c9a58d3c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'input': 'who is a female voice actress who does animal voices',\n", + " 'chat_history': [],\n", + " 'agent_outcome': AgentFinish(return_values={'output': ''}, log=''),\n", + " 'agent_scratchpad': [],\n", + " 'intermediate_steps': []}" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "result2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "823fc0fd-ebce-4968-b8e8-ba6f7be47b34", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.11.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/langchain_vids/chat_agent_executor.ipynb b/langchain_vids/chat_agent_executor.ipynb new file mode 100644 index 0000000..1bf103a --- /dev/null +++ b/langchain_vids/chat_agent_executor.ipynb @@ -0,0 +1,290 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 38, + "id": "d92bf399-f5a1-4df3-b69f-61ea56f25b5a", + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "import os\n", + "\n", + "# Get the directory of the current notebook\n", + "current_dir = os.path.dirname(os.path.abspath('__file__'))\n", + "\n", + "# Move up to the root directory\n", + "root_dir = os.path.abspath(os.path.join(current_dir, '..'))\n", + "\n", + "# Add the root directory to the sys.path\n", + "sys.path.append(root_dir)\n", + "\n", + "from graph_gen.gen_graph import gen_graph\n", + "from langchain_community.tools.tavily_search import TavilySearchResults\n", + "from langchain import hub\n", + "from langchain_openai.chat_models import ChatOpenAI\n", + "from langchain.agents import create_openai_functions_agent\n", + "from langgraph.prebuilt.tool_executor import ToolExecutor\n", + "from typing import Annotated, Dict, List, Optional, TypedDict, Tuple, Sequence, Union, Literal\n", + "from langchain_core.messages import AIMessage, BaseMessage, FunctionMessage, HumanMessage, ToolMessage\n", + "from langgraph.graph import END, StateGraph, MessageGraph\n", + "from langchain_core.agents import AgentAction, AgentFinish\n", + "from langchain_core.utils.function_calling import convert_to_openai_function\n", + "from langchain.output_parsers.openai_tools import (\n", + " JsonOutputToolsParser,\n", + " PydanticToolsParser\n", + ")\n", + "from langchain.agents.output_parsers.openai_functions import OpenAIFunctionsAgentOutputParser\n", + "import operator\n", + "import re" + ] + }, + { + "cell_type": "markdown", + "id": "4a38655e-9eff-4017-9054-7e86e7074644", + "metadata": {}, + "source": [ + "### [LangGraph: Chat Agent Executor](https://www.youtube.com/watch?v=Un-88uJKdiU&list=PLfaIDFEXuae16n2TWUkKq5PgJ0w6Pkwtg&index=3) \"YouTube\"" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "f40d8d93-9043-4997-8eb1-53fc0e96fde8", + "metadata": {}, + "outputs": [], + "source": [ + "# Graph \n", + "graph_spec = \"\"\"\n", + "\n", + "call_model(AgentState)\n", + " has_function_call => call_tool\n", + "\n", + "call_tool\n", + " => call_model\n", + "\n", + "\"\"\"\n", + "\n", + "# Conditional edges\n", + "def has_function_call(state):\n", + " last_message = state[\"messages\"][-1]\n", + " return \"function_call\" in last_message.additional_kwargs" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "962a8104-b367-48fd-83e6-77e3c53f22c3", + "metadata": {}, + "outputs": [], + "source": [ + "# State\n", + "class AgentState(TypedDict):\n", + " messages: Annotated[Sequence[BaseMessage], operator.add]\n", + " intermediate_steps: Annotated[Sequence[BaseMessage], operator.add]" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "1c9edc78-fa94-40f9-992f-5253c14b9a76", + "metadata": {}, + "outputs": [], + "source": [ + "# Tools\n", + "tools = [TavilySearchResults(max_results=1)]\n", + "functions = [convert_to_openai_function(tool) for tool in tools]\n", + "model = ChatOpenAI(model=\"gpt-4o\", temperature=0, streaming=True)\n", + "model = model.bind_functions(functions)\n", + "tool_executor = ToolExecutor(tools)\n", + "\n", + "def print_result(s):\n", + " if 'agent' in s and 'agent_outcome' in s['agent'] and isinstance(s['agent']['agent_outcome'], AgentFinish):\n", + " print(s['agent']['agent_outcome'].return_values['output'])\n", + " else:\n", + " print(s)\n", + " print()" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "id": "5f30f7de-aae1-496d-9d0d-9a6751b49f3f", + "metadata": {}, + "outputs": [], + "source": [ + "# Nodes\n", + "def call_model(state):\n", + " messages = state[\"messages\"]\n", + " response = model.invoke(messages)\n", + " return { \"messages\": [response] }\n", + "\n", + "def call_tool(state):\n", + " messages = state[\"messages\"]\n", + " last_message = messages[-1]\n", + " action = ToolInvocation(\n", + " tool=last_message.additional_kwargs[\"function_call\"][\"name\"],\n", + " tool_input=json.loads(last_message.additional_kwargs[\"function_call\"][\"arguments\"])\n", + " )\n", + " response = tool_executor.invoke(action)\n", + " function_message = FunctionMessage(content=str(response), name=action.tool)\n", + " return { \"intermediate_steps\": [function_message] }" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "id": "5133d0ba-d5a7-40ee-b772-b41aea2c4da8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'call_model': {'messages': [AIMessage(content='One of the most famous voice actresses from the 1950s is June Foray. She is best known for her work in animated television shows and films. Some of her most iconic roles include the voice of Rocky the Flying Squirrel and Natasha Fatale in \"The Rocky and Bullwinkle Show,\" as well as Granny in the \"Looney Tunes\" series. June Foray\\'s extensive career and versatile voice acting made her a legendary figure in the animation industry.', response_metadata={'finish_reason': 'stop', 'model_name': 'gpt-4o-2024-05-13', 'system_fingerprint': 'fp_3aa7262c27'}, id='run-4b4354d6-f740-4e17-8526-8aaace63b01e-0')]}}\n", + "\n" + ] + } + ], + "source": [ + "# Run the graph\n", + "# - generate the python langgraph code\n", + "# - execute the code, runnable graph in variable 'app'\n", + "# - test the graph\n", + "graph_code = gen_graph(\"chat_agent_executor\", graph_spec)\n", + "exec(graph_code)\n", + "\n", + "# 'graph' contains the compiled graph\n", + "inputs = { \"messages\": [HumanMessage(content=\"who is a famous voice actress from the 50s\")], \"intermediate_steps\": [] }\n", + "for s in chat_agent_executor.stream(inputs):\n", + " print_result(s)" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "id": "8d5fef9c-2e13-4633-a45d-605a15d0c28d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "chat_agent_executor = StateGraph(AgentState)\n", + "chat_agent_executor.add_node('call_model', call_model)\n", + "chat_agent_executor.add_node('call_tool', call_tool)\n", + "\n", + "chat_agent_executor.set_entry_point('call_model')\n", + "\n", + "def after_call_model(state: AgentState):\n", + " if has_function_call(state):\n", + " return 'call_tool'\n", + " return END\n", + "\n", + "call_model_dict = {'call_tool': 'call_tool', END: END}\n", + "chat_agent_executor.add_conditional_edges('call_model', after_call_model, call_model_dict)\n", + "\n", + "chat_agent_executor.add_edge('call_tool', 'call_model')\n", + "\n", + "chat_agent_executor = chat_agent_executor.compile()\n" + ] + } + ], + "source": [ + "print(graph_code)" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "id": "36736d70-8940-4d69-b778-2b90051ece77", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'call_model': {'messages': [AIMessage(content='', additional_kwargs={'function_call': {'arguments': '{\"query\":\"who invented Tonal\"}', 'name': 'tavily_search_results_json'}}, response_metadata={'finish_reason': 'function_call', 'model_name': 'gpt-4o-2024-05-13', 'system_fingerprint': 'fp_3aa7262c27'}, id='run-de1d3c26-3cd7-40c1-b07d-862dc29bfba7-0')]}}\n", + "{'function_call': {'arguments': '{\"query\":\"who invented Tonal\"}', 'name': 'tavily_search_results_json'}}\n", + "{'call_tool': {'intermediate_steps': [FunctionMessage(content='[{\\'url\\': \\'https://www.businessinsider.com/tonal-review-home-fitness-startup-2019-11?op=1\\', \\'content\\': \"Tonal was invented by Aly Orady, a Hewlett-Packard veteran who wanted an easier way to stay in shape at home that didn\\'t involve sweaty, used equipment and tedious trips to the gym.\"}]', name='tavily_search_results_json')]}}\n", + "{'call_model': {'messages': [AIMessage(content='Tonal was invented by Aly Orady. He founded the company in 2015 with the aim of creating a more efficient and effective way to strength train at home using digital weights and advanced technology.', response_metadata={'finish_reason': 'stop', 'model_name': 'gpt-4o-2024-05-13', 'system_fingerprint': 'fp_c9aa9c0491'}, id='run-54b7f559-05f8-46f6-a653-8b91ce8656f7-0')]}}\n", + "\n", + "Tonal was invented by Aly Orady. He founded the company in 2015 with the aim of creating a more efficient and effective way to strength train at home using digital weights and advanced technology.\n" + ] + } + ], + "source": [ + "messages = [HumanMessage(content=\"who invented tonal?\")]\n", + "for s in chat_agent_executor.stream({\"messages\": messages, \"intermediate_steps\": []}):\n", + " print(s)\n", + " if 'call_model' in s and 'messages' in s['call_model']:\n", + " message = s['call_model']['messages'][-1]\n", + " print(f\"\\n{message.content}\") if message.content else print(message.additional_kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "id": "ce525932-caa0-451c-becc-9504b3d062d6", + "metadata": {}, + "outputs": [ + { + "data": { + "image/jpeg": "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", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from IPython.display import Image, display\n", + "\n", + "try:\n", + " display(Image(chat_agent_executor.get_graph().draw_mermaid_png()))\n", + "except Exception:\n", + " # This requires some extra dependencies and is optional\n", + " pass" + ] + }, + { + "cell_type": "markdown", + "id": "de7a22e1-b12b-4b09-a3e1-92d785b57058", + "metadata": {}, + "source": [ + "### " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2b5e69c2-aa9b-44d7-b7d9-f9a6f36b1eef", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.11.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}