[Docs] Update notebooks to use START (#902)

This commit is contained in:
William FH
2024-07-01 21:36:34 -07:00
committed by GitHub
parent 267f5e5234
commit 727e63c01e
67 changed files with 1059 additions and 20258 deletions
@@ -27,10 +27,7 @@
"id": "af4ce0ba-7596-4e5f-8bf8-0b0bd6e62833",
"metadata": {},
"outputs": [],
"source": [
"%%capture --no-stderr\n",
"%pip install --quiet -U langgraph langchain langchain_openai tavily-python"
]
"source": ["%%capture --no-stderr\n%pip install --quiet -U langgraph langchain langchain_openai tavily-python"]
},
{
"cell_type": "markdown",
@@ -46,13 +43,7 @@
"id": "c903a1cf-2977-4e2d-ad7d-8b3946821d89",
"metadata": {},
"outputs": [],
"source": [
"import getpass\n",
"import os\n",
"\n",
"os.environ[\"OPENAI_API_KEY\"] = getpass.getpass(\"OpenAI API Key:\")\n",
"os.environ[\"TAVILY_API_KEY\"] = getpass.getpass(\"Tavily API Key:\")"
]
"source": ["import getpass\nimport os\n\nos.environ[\"OPENAI_API_KEY\"] = getpass.getpass(\"OpenAI API Key:\")\nos.environ[\"TAVILY_API_KEY\"] = getpass.getpass(\"Tavily API Key:\")"]
},
{
"cell_type": "markdown",
@@ -68,10 +59,7 @@
"id": "95e25aec-7c9f-4a63-b143-225d0e9a79c3",
"metadata": {},
"outputs": [],
"source": [
"os.environ[\"LANGCHAIN_TRACING_V2\"] = \"true\"\n",
"os.environ[\"LANGCHAIN_API_KEY\"] = getpass.getpass(\"LangSmith API Key:\")"
]
"source": ["os.environ[\"LANGCHAIN_TRACING_V2\"] = \"true\"\nos.environ[\"LANGCHAIN_API_KEY\"] = getpass.getpass(\"LangSmith API Key:\")"]
},
{
"cell_type": "markdown",
@@ -95,11 +83,7 @@
"id": "d7ef57dd-5d6e-4ad3-9377-a92201c1310e",
"metadata": {},
"outputs": [],
"source": [
"from langchain_community.tools.tavily_search import TavilySearchResults\n",
"\n",
"tools = [TavilySearchResults(max_results=1)]"
]
"source": ["from langchain_community.tools.tavily_search import TavilySearchResults\n\ntools = [TavilySearchResults(max_results=1)]"]
},
{
"cell_type": "markdown",
@@ -123,11 +107,7 @@
"id": "892b54b9-75f0-4804-9ed0-88b5e5532989",
"metadata": {},
"outputs": [],
"source": [
"from langchain_openai import ChatOpenAI\n",
"\n",
"model = ChatOpenAI(temperature=0)"
]
"source": ["from langchain_openai import ChatOpenAI\n\nmodel = ChatOpenAI(temperature=0)"]
},
{
"cell_type": "markdown",
@@ -145,9 +125,7 @@
"id": "cd3cbae5-d92c-4559-a4aa-44721b80d107",
"metadata": {},
"outputs": [],
"source": [
"model = model.bind_tools(tools)"
]
"source": ["model = model.bind_tools(tools)"]
},
{
"cell_type": "markdown",
@@ -173,16 +151,7 @@
"id": "ea793afa-2eab-4901-910d-6eed90cd6564",
"metadata": {},
"outputs": [],
"source": [
"import operator\n",
"from typing import Annotated, Sequence, TypedDict\n",
"\n",
"from langchain_core.messages import BaseMessage\n",
"\n",
"\n",
"class AgentState(TypedDict):\n",
" messages: Annotated[Sequence[BaseMessage], operator.add]"
]
"source": ["import operator\nfrom typing import Annotated, Sequence, TypedDict\n\nfrom langchain_core.messages import BaseMessage\n\n\nclass AgentState(TypedDict):\n messages: Annotated[Sequence[BaseMessage], operator.add]"]
},
{
"cell_type": "markdown",
@@ -217,33 +186,7 @@
"id": "3b541bb9-900c-40d0-964d-7b5dfee30667",
"metadata": {},
"outputs": [],
"source": [
"from langgraph.prebuilt import ToolNode\n",
"\n",
"\n",
"# Define the function that determines whether to continue or not\n",
"def should_continue(state):\n",
" messages = state[\"messages\"]\n",
" last_message = messages[-1]\n",
" # If there are no tool calls, then we finish\n",
" if not last_message.tool_calls:\n",
" return \"end\"\n",
" # Otherwise if there is, we continue\n",
" else:\n",
" return \"continue\"\n",
"\n",
"\n",
"# Define the function that calls the model\n",
"def call_model(state):\n",
" messages = state[\"messages\"]\n",
" response = model.invoke(messages)\n",
" # We return a list, because this will get added to the existing list\n",
" return {\"messages\": [response]}\n",
"\n",
"\n",
"# Define the function to execute tools\n",
"tool_node = ToolNode(tools)"
]
"source": ["from langgraph.prebuilt import ToolNode\n\n\n# Define the function that determines whether to continue or not\ndef should_continue(state):\n messages = state[\"messages\"]\n last_message = messages[-1]\n # If there are no tool calls, then we finish\n if not last_message.tool_calls:\n return \"end\"\n # Otherwise if there is, we continue\n else:\n return \"continue\"\n\n\n# Define the function that calls the model\ndef call_model(state):\n messages = state[\"messages\"]\n response = model.invoke(messages)\n # We return a list, because this will get added to the existing list\n return {\"messages\": [response]}\n\n\n# Define the function to execute tools\ntool_node = ToolNode(tools)"]
},
{
"cell_type": "markdown",
@@ -261,50 +204,7 @@
"id": "813ae66c-3b58-4283-a02a-36da72a2ab90",
"metadata": {},
"outputs": [],
"source": [
"from langgraph.graph import END, StateGraph\n",
"\n",
"# Define a new graph\n",
"workflow = StateGraph(AgentState)\n",
"\n",
"# Define the two nodes we will cycle between\n",
"workflow.add_node(\"agent\", call_model)\n",
"workflow.add_node(\"action\", tool_node)\n",
"\n",
"# Set the entrypoint as `agent`\n",
"# This means that this node is the first one called\n",
"workflow.set_entry_point(\"agent\")\n",
"\n",
"# We now add a conditional edge\n",
"workflow.add_conditional_edges(\n",
" # First, we define the start node. We use `agent`.\n",
" # This means these are the edges taken after the `agent` node is called.\n",
" \"agent\",\n",
" # Next, we pass in the function that will determine which node is called next.\n",
" should_continue,\n",
" # Finally we pass in a mapping.\n",
" # The keys are strings, and the values are other nodes.\n",
" # END is a special node marking that the graph should finish.\n",
" # What will happen is we will call `should_continue`, and then the output of that\n",
" # will be matched against the keys in this mapping.\n",
" # Based on which one it matches, that node will then be called.\n",
" {\n",
" # If `tools`, then we call the tool node.\n",
" \"continue\": \"action\",\n",
" # Otherwise we finish.\n",
" \"end\": END,\n",
" },\n",
")\n",
"\n",
"# We now add a normal edge from `tools` to `agent`.\n",
"# This means that after `tools` is called, `agent` node is called next.\n",
"workflow.add_edge(\"action\", \"agent\")\n",
"\n",
"# Finally, we compile it!\n",
"# This compiles it into a LangChain Runnable,\n",
"# meaning you can use it as you would any other runnable\n",
"app = workflow.compile()"
]
"source": ["from langgraph.graph import END, StateGraph, START\n\n# Define a new graph\nworkflow = StateGraph(AgentState)\n\n# Define the two nodes we will cycle between\nworkflow.add_node(\"agent\", call_model)\nworkflow.add_node(\"action\", tool_node)\n\n# Set the entrypoint as `agent`\n# This means that this node is the first one called\nworkflow.add_edge(START, \"agent\")\n\n# We now add a conditional edge\nworkflow.add_conditional_edges(\n # First, we define the start node. We use `agent`.\n # This means these are the edges taken after the `agent` node is called.\n \"agent\",\n # Next, we pass in the function that will determine which node is called next.\n should_continue,\n # Finally we pass in a mapping.\n # The keys are strings, and the values are other nodes.\n # END is a special node marking that the graph should finish.\n # What will happen is we will call `should_continue`, and then the output of that\n # will be matched against the keys in this mapping.\n # Based on which one it matches, that node will then be called.\n {\n # If `tools`, then we call the tool node.\n \"continue\": \"action\",\n # Otherwise we finish.\n \"end\": END,\n },\n)\n\n# We now add a normal edge from `tools` to `agent`.\n# This means that after `tools` is called, `agent` node is called next.\nworkflow.add_edge(\"action\", \"agent\")\n\n# Finally, we compile it!\n# This compiles it into a LangChain Runnable,\n# meaning you can use it as you would any other runnable\napp = workflow.compile()"]
},
{
"cell_type": "markdown",
@@ -337,12 +237,7 @@
"output_type": "execute_result"
}
],
"source": [
"from langchain_core.messages import HumanMessage\n",
"\n",
"inputs = {\"messages\": [HumanMessage(content=\"what is the weather in sf\")]}\n",
"app.invoke(inputs)"
]
"source": ["from langchain_core.messages import HumanMessage\n\ninputs = {\"messages\": [HumanMessage(content=\"what is the weather in sf\")]}\napp.invoke(inputs)"]
},
{
"cell_type": "markdown",
@@ -392,16 +287,7 @@
]
}
],
"source": [
"inputs = {\"messages\": [HumanMessage(content=\"what is the weather in sf\")]}\n",
"for output in app.stream(inputs):\n",
" # stream() yields dictionaries with output keyed by node name\n",
" for key, value in output.items():\n",
" print(f\"Output from node '{key}':\")\n",
" print(\"---\")\n",
" print(value)\n",
" print(\"\\n---\\n\")"
]
"source": ["inputs = {\"messages\": [HumanMessage(content=\"what is the weather in sf\")]}\nfor output in app.stream(inputs):\n # stream() yields dictionaries with output keyed by node name\n for key, value in output.items():\n print(f\"Output from node '{key}':\")\n print(\"---\")\n print(value)\n print(\"\\n---\\n\")"]
},
{
"cell_type": "markdown",
@@ -496,21 +382,7 @@
]
}
],
"source": [
"inputs = {\"messages\": [HumanMessage(content=\"what is the weather in sf?\")]}\n",
"\n",
"async for output in app.astream_log(inputs, include_types=[\"llm\"]):\n",
" # astream_log() yields the requested logs (here LLMs) in JSONPatch format\n",
" for op in output.ops:\n",
" if op[\"path\"] == \"/streamed_output/-\":\n",
" # this is the output from .stream()\n",
" ...\n",
" elif op[\"path\"].startswith(\"/logs/\") and op[\"path\"].endswith(\n",
" \"/streamed_output/-\"\n",
" ):\n",
" # because we chose to only include LLMs, these are LLM tokens\n",
" print(op[\"value\"])"
]
"source": ["inputs = {\"messages\": [HumanMessage(content=\"what is the weather in sf?\")]}\n\nasync for output in app.astream_log(inputs, include_types=[\"llm\"]):\n # astream_log() yields the requested logs (here LLMs) in JSONPatch format\n for op in output.ops:\n if op[\"path\"] == \"/streamed_output/-\":\n # this is the output from .stream()\n ...\n elif op[\"path\"].startswith(\"/logs/\") and op[\"path\"].endswith(\n \"/streamed_output/-\"\n ):\n # because we chose to only include LLMs, these are LLM tokens\n print(op[\"value\"])"]
},
{
"cell_type": "code",
@@ -518,7 +390,7 @@
"id": "08ae8246-11d5-40e1-8567-361e5bef8917",
"metadata": {},
"outputs": [],
"source": []
"source": [""]
}
],
"metadata": {