From ec8fca977ecd9de9259addd68f65f2f2fcdfdb70 Mon Sep 17 00:00:00 2001 From: isaac hershenson Date: Tue, 18 Jun 2024 14:45:06 -0700 Subject: [PATCH] fmt --- docs/docs/deploy/how_tos/background_run.ipynb | 16 ++-- docs/docs/deploy/how_tos/configuration.ipynb | 16 ++-- docs/docs/deploy/how_tos/double_texting.ipynb | 16 ++-- .../deploy/how_tos/human-in-the-loop.ipynb | 74 ++++++++++------- docs/docs/deploy/how_tos/same-thread.ipynb | 20 ++++- .../docs/deploy/how_tos/stream_messages.ipynb | 38 +++++---- docs/docs/deploy/how_tos/stream_updates.ipynb | 11 ++- docs/docs/deploy/how_tos/stream_values.ipynb | 10 ++- examples/learning.ipynb | 6 +- examples/time-travel.ipynb | 6 +- examples/tutorials/sql-agent.ipynb | 80 +++++++++++++------ langgraph/graph/graph.py | 6 +- langgraph/managed/base.py | 3 +- langgraph/prebuilt/__init__.py | 1 + langgraph/pregel/__init__.py | 12 +-- langgraph/pregel/retry.py | 6 +- langgraph/serde/base.py | 6 +- 17 files changed, 202 insertions(+), 125 deletions(-) diff --git a/docs/docs/deploy/how_tos/background_run.ipynb b/docs/docs/deploy/how_tos/background_run.ipynb index 87efa3a0b..52e2f50cb 100644 --- a/docs/docs/deploy/how_tos/background_run.ipynb +++ b/docs/docs/deploy/how_tos/background_run.ipynb @@ -125,7 +125,7 @@ ], "source": [ "# If we list runs on this thread, we can see it is empty\n", - "runs = await client.runs.list(thread['thread_id'])\n", + "runs = await client.runs.list(thread[\"thread_id\"])\n", "runs" ] }, @@ -138,7 +138,9 @@ "source": [ "# Let's kick off a run\n", "input = {\"messages\": [{\"role\": \"human\", \"content\": \"whats the weather in sf\"}]}\n", - "run = await client.runs.create(thread['thread_id'], assistant[\"assistant_id\"], input=input)\n" + "run = await client.runs.create(\n", + " thread[\"thread_id\"], assistant[\"assistant_id\"], input=input\n", + ")" ] }, { @@ -166,7 +168,7 @@ ], "source": [ "# The first time we poll it, we can see `status=pending`\n", - "await client.runs.get(thread['thread_id'], run['run_id'])" + "await client.runs.get(thread[\"thread_id\"], run[\"run_id\"])" ] }, { @@ -449,7 +451,7 @@ ], "source": [ "# We can list events for the run\n", - "await client.runs.list_events(thread['thread_id'], run['run_id'])" + "await client.runs.list_events(thread[\"thread_id\"], run[\"run_id\"])" ] }, { @@ -477,7 +479,7 @@ ], "source": [ "# Eventually, it should finish and we should see `status=success`\n", - "await client.runs.get(thread['thread_id'], run['run_id'])" + "await client.runs.get(thread[\"thread_id\"], run[\"run_id\"])" ] }, { @@ -488,7 +490,7 @@ "outputs": [], "source": [ "# We can get the final results\n", - "results = await client.runs.list_events(thread['thread_id'], run['run_id'])" + "results = await client.runs.list_events(thread[\"thread_id\"], run[\"run_id\"])" ] }, { @@ -589,7 +591,7 @@ ], "source": [ "# We can get the content of the final message\n", - "final_result['data']['output']['messages'][-1]['content']" + "final_result[\"data\"][\"output\"][\"messages\"][-1][\"content\"]" ] }, { diff --git a/docs/docs/deploy/how_tos/configuration.ipynb b/docs/docs/deploy/how_tos/configuration.ipynb index 3d427bd0d..e8f00027f 100644 --- a/docs/docs/deploy/how_tos/configuration.ipynb +++ b/docs/docs/deploy/how_tos/configuration.ipynb @@ -68,7 +68,7 @@ "# We can do this by getting the default assistant\n", "# There should always be a default assistant with no configuration\n", "assistants = await client.assistants.search()\n", - "assistants = [a for a in assistants if not a['config']]\n", + "assistants = [a for a in assistants if not a[\"config\"]]\n", "base_assistant = assistants[0]" ] }, @@ -93,10 +93,12 @@ ], "source": [ "# We can now call `.get_schemas` to get schemas associated with this graph\n", - "schemas = await client.assistants.get_schemas(assistant_id=base_assistant[\"assistant_id\"])\n", + "schemas = await client.assistants.get_schemas(\n", + " assistant_id=base_assistant[\"assistant_id\"]\n", + ")\n", "# There are multiple types of schemas\n", "# We can get the `config_schema` to look at the the configurable parameters\n", - "schemas['config_schema']['definitions']['Configurable']['properties']" + "schemas[\"config_schema\"][\"definitions\"][\"Configurable\"][\"properties\"]" ] }, { @@ -106,7 +108,9 @@ "metadata": {}, "outputs": [], "source": [ - "assistant = await client.assistants.create(graph_id=\"agent\", config={\"configurable\": {\"model_name\": \"openai\"}})" + "assistant = await client.assistants.create(\n", + " graph_id=\"agent\", config={\"configurable\": {\"model_name\": \"openai\"}}\n", + ")" ] }, { @@ -163,7 +167,9 @@ "source": [ "thread = await client.threads.create()\n", "input = {\"messages\": [{\"role\": \"user\", \"content\": \"who made you?\"}]}\n", - "async for event in client.runs.stream(thread['thread_id'], assistant['assistant_id'], input=input):\n", + "async for event in client.runs.stream(\n", + " thread[\"thread_id\"], assistant[\"assistant_id\"], input=input\n", + "):\n", " print(event)" ] }, diff --git a/docs/docs/deploy/how_tos/double_texting.ipynb b/docs/docs/deploy/how_tos/double_texting.ipynb index b5862eb85..e4c90f12c 100644 --- a/docs/docs/deploy/how_tos/double_texting.ipynb +++ b/docs/docs/deploy/how_tos/double_texting.ipynb @@ -32,9 +32,9 @@ "metadata": {}, "outputs": [], "source": [ - "from langgraph_sdk import get_client\n", + "import httpx\n", "from langchain_core.messages import convert_to_messages\n", - "import httpx" + "from langgraph_sdk import get_client" ] }, { @@ -77,7 +77,7 @@ "run = await client.runs.create(\n", " thread[\"thread_id\"],\n", " assistant[\"assistant_id\"],\n", - " input={\"messages\": [{\"role\": \"human\", \"content\": \"whats the weather in sf?\"}]}\n", + " input={\"messages\": [{\"role\": \"human\", \"content\": \"whats the weather in sf?\"}]},\n", ")" ] }, @@ -222,7 +222,8 @@ "source": [ "# the first run will be interrupted\n", "interrupted_run = await client.runs.create(\n", - " thread[\"thread_id\"], assistant[\"assistant_id\"],\n", + " thread[\"thread_id\"],\n", + " assistant[\"assistant_id\"],\n", " input={\"messages\": [{\"role\": \"human\", \"content\": \"whats the weather in sf?\"}]},\n", ")\n", "await asyncio.sleep(2)\n", @@ -377,7 +378,8 @@ "source": [ "# the first run will be interrupted\n", "rolled_back_run = await client.runs.create(\n", - " thread[\"thread_id\"], assistant[\"assistant_id\"],\n", + " thread[\"thread_id\"],\n", + " assistant[\"assistant_id\"],\n", " input={\"messages\": [{\"role\": \"human\", \"content\": \"whats the weather in sf?\"}]},\n", ")\n", "await asyncio.sleep(2)\n", @@ -479,7 +481,7 @@ "source": [ "try:\n", " await client.runs.get(thread[\"thread_id\"], rolled_back_run[\"run_id\"])\n", - "except httpx.HTTPStatusError as e:\n", + "except httpx.HTTPStatusError as _:\n", " print(\"Original run was correctly deleted\")" ] }, @@ -512,7 +514,7 @@ "first_run = await client.runs.create(\n", " thread[\"thread_id\"],\n", " assistant[\"assistant_id\"],\n", - " input={\"messages\": [{\"role\": \"human\", \"content\": \"whats the weather in sf?\"}]}\n", + " input={\"messages\": [{\"role\": \"human\", \"content\": \"whats the weather in sf?\"}]},\n", ")" ] }, diff --git a/docs/docs/deploy/how_tos/human-in-the-loop.ipynb b/docs/docs/deploy/how_tos/human-in-the-loop.ipynb index 9ab91a93f..447d144e7 100644 --- a/docs/docs/deploy/how_tos/human-in-the-loop.ipynb +++ b/docs/docs/deploy/how_tos/human-in-the-loop.ipynb @@ -60,7 +60,7 @@ "source": [ "# There should always be a default assistant with no configuration\n", "assistants = await client.assistants.search()\n", - "assistants = [a for a in assistants if not a['config']]\n", + "assistants = [a for a in assistants if not a[\"config\"]]\n", "assistants" ] }, @@ -142,7 +142,7 @@ } ], "source": [ - "runs = await client.runs.list(thread['thread_id'])\n", + "runs = await client.runs.list(thread[\"thread_id\"])\n", "runs" ] }, @@ -188,7 +188,11 @@ "source": [ "input = {\"messages\": [{\"role\": \"human\", \"content\": \"whats the weather in sf\"}]}\n", "async for chunk in client.runs.stream(\n", - " thread['thread_id'], assistant['assistant_id'], input=input, stream_mode=\"updates\", interrupt_before=['action']\n", + " thread[\"thread_id\"],\n", + " assistant[\"assistant_id\"],\n", + " input=input,\n", + " stream_mode=\"updates\",\n", + " interrupt_before=[\"action\"],\n", "):\n", " print(f\"Receiving new event of type: {chunk.event}...\")\n", " print(chunk.data)\n", @@ -239,7 +243,11 @@ "source": [ "input = None\n", "async for chunk in client.runs.stream(\n", - " thread['thread_id'], assistant['assistant_id'], input=input, stream_mode=\"updates\", interrupt_before=['action']\n", + " thread[\"thread_id\"],\n", + " assistant[\"assistant_id\"],\n", + " input=input,\n", + " stream_mode=\"updates\",\n", + " interrupt_before=[\"action\"],\n", "):\n", " print(f\"Receiving new event of type: {chunk.event}...\")\n", " print(chunk.data)\n", @@ -289,7 +297,11 @@ "source": [ "input = {\"messages\": [{\"role\": \"human\", \"content\": \"whats the weather in la?\"}]}\n", "async for chunk in client.runs.stream(\n", - " thread['thread_id'], assistant['assistant_id'], input=input, stream_mode=\"updates\", interrupt_before=['action']\n", + " thread[\"thread_id\"],\n", + " assistant[\"assistant_id\"],\n", + " input=input,\n", + " stream_mode=\"updates\",\n", + " interrupt_before=[\"action\"],\n", "):\n", " print(f\"Receiving new event of type: {chunk.event}...\")\n", " print(chunk.data)\n", @@ -311,7 +323,7 @@ "metadata": {}, "outputs": [], "source": [ - "thread_state = await client.threads.get_state(thread['thread_id'])" + "thread_state = await client.threads.get_state(thread[\"thread_id\"])" ] }, { @@ -329,7 +341,7 @@ "metadata": {}, "outputs": [], "source": [ - "last_message = thread_state['values']['messages'][-1]" + "last_message = thread_state[\"values\"][\"messages\"][-1]" ] }, { @@ -353,7 +365,7 @@ } ], "source": [ - "last_message['content']" + "last_message[\"content\"]" ] }, { @@ -371,12 +383,14 @@ "metadata": {}, "outputs": [], "source": [ - "last_message['tool_calls'] = [{\n", - " 'id': last_message['tool_calls'][0]['id'],\n", - " 'name': 'tavily_search_results_json',\n", - " # We change the query to say temperature\n", - " 'args': {'query': 'weather in Louisiana'}\n", - "}]\n", + "last_message[\"tool_calls\"] = [\n", + " {\n", + " \"id\": last_message[\"tool_calls\"][0][\"id\"],\n", + " \"name\": \"tavily_search_results_json\",\n", + " # We change the query to say temperature\n", + " \"args\": {\"query\": \"weather in Louisiana\"},\n", + " }\n", + "]\n", "# last_message['content'] = [{\n", "# 'id': last_message['content'][0]['id'],\n", "# 'name': 'tavily_search_results_json',\n", @@ -413,7 +427,9 @@ } ], "source": [ - "await client.threads.update_state(thread['thread_id'], values={\"messages\": [last_message]})" + "await client.threads.update_state(\n", + " thread[\"thread_id\"], values={\"messages\": [last_message]}\n", + ")" ] }, { @@ -444,8 +460,8 @@ } ], "source": [ - "thread_state = await client.threads.get_state(thread['thread_id'])\n", - "thread_state['values']['messages'][-1]['tool_calls']" + "thread_state = await client.threads.get_state(thread[\"thread_id\"])\n", + "thread_state[\"values\"][\"messages\"][-1][\"tool_calls\"]" ] }, { @@ -492,7 +508,11 @@ "source": [ "input = None\n", "async for chunk in client.runs.stream(\n", - " thread['thread_id'], assistant['assistant_id'], input=input, stream_mode=\"updates\", interrupt_before=['action']\n", + " thread[\"thread_id\"],\n", + " assistant[\"assistant_id\"],\n", + " input=input,\n", + " stream_mode=\"updates\",\n", + " interrupt_before=[\"action\"],\n", "):\n", " print(f\"Receiving new event of type: {chunk.event}...\")\n", " print(chunk.data)\n", @@ -517,7 +537,7 @@ "metadata": {}, "outputs": [], "source": [ - "thread_history = await client.threads.get_history(thread['thread_id'], limit=100)" + "thread_history = await client.threads.get_history(thread[\"thread_id\"], limit=100)" ] }, { @@ -571,7 +591,7 @@ ], "source": [ "rewind_state = thread_history[3]\n", - "rewind_state['values']['messages'][-1]['tool_calls']" + "rewind_state[\"values\"][\"messages\"][-1][\"tool_calls\"]" ] }, { @@ -593,7 +613,7 @@ } ], "source": [ - "rewind_state['config']" + "rewind_state[\"config\"]" ] }, { @@ -640,12 +660,12 @@ "source": [ "input = None\n", "async for chunk in client.runs.stream(\n", - " thread['thread_id'], \n", - " assistant['assistant_id'], \n", - " input=input, \n", - " stream_mode=\"updates\", \n", - " interrupt_before=['action'],\n", - " config=rewind_state['config']\n", + " thread[\"thread_id\"],\n", + " assistant[\"assistant_id\"],\n", + " input=input,\n", + " stream_mode=\"updates\",\n", + " interrupt_before=[\"action\"],\n", + " config=rewind_state[\"config\"],\n", "):\n", " print(f\"Receiving new event of type: {chunk.event}...\")\n", " print(chunk.data)\n", diff --git a/docs/docs/deploy/how_tos/same-thread.ipynb b/docs/docs/deploy/how_tos/same-thread.ipynb index 94d08a04e..077ac4417 100644 --- a/docs/docs/deploy/how_tos/same-thread.ipynb +++ b/docs/docs/deploy/how_tos/same-thread.ipynb @@ -23,11 +23,13 @@ "\n", "client = get_client()\n", "\n", - "openai_assistant = await client.assistants.create(graph_id=\"agent\", config={\"configurable\": {\"model_name\": \"openai\"}})\n", + "openai_assistant = await client.assistants.create(\n", + " graph_id=\"agent\", config={\"configurable\": {\"model_name\": \"openai\"}}\n", + ")\n", "\n", "# There should always be a default assistant with no configuration\n", "assistants = await client.assistants.search()\n", - "default_assistant = [a for a in assistants if not a['config']][0]" + "default_assistant = [a for a in assistants if not a[\"config\"]][0]" ] }, { @@ -117,7 +119,12 @@ "source": [ "thread = await client.threads.create()\n", "input = {\"messages\": [{\"role\": \"user\", \"content\": \"who made you?\"}]}\n", - "async for event in client.runs.stream(thread['thread_id'], openai_assistant['assistant_id'], input=input, stream_mode='updates'):\n", + "async for event in client.runs.stream(\n", + " thread[\"thread_id\"],\n", + " openai_assistant[\"assistant_id\"],\n", + " input=input,\n", + " stream_mode=\"updates\",\n", + "):\n", " print(event)" ] }, @@ -147,7 +154,12 @@ ], "source": [ "input = {\"messages\": [{\"role\": \"user\", \"content\": \"and you?\"}]}\n", - "async for event in client.runs.stream(thread['thread_id'], default_assistant['assistant_id'], input=input, stream_mode='updates'):\n", + "async for event in client.runs.stream(\n", + " thread[\"thread_id\"],\n", + " default_assistant[\"assistant_id\"],\n", + " input=input,\n", + " stream_mode=\"updates\",\n", + "):\n", " print(event)" ] }, diff --git a/docs/docs/deploy/how_tos/stream_messages.ipynb b/docs/docs/deploy/how_tos/stream_messages.ipynb index 60439088d..ede2e7d4e 100644 --- a/docs/docs/deploy/how_tos/stream_messages.ipynb +++ b/docs/docs/deploy/how_tos/stream_messages.ipynb @@ -63,7 +63,9 @@ "metadata": {}, "outputs": [], "source": [ - "assistant = await client.assistants.create(graph_id=\"agent\", config={\"configurable\": {\"model_name\": \"openai\"}})" + "assistant = await client.assistants.create(\n", + " graph_id=\"agent\", config={\"configurable\": {\"model_name\": \"openai\"}}\n", + ")" ] }, { @@ -135,7 +137,7 @@ } ], "source": [ - "runs = await client.runs.list(thread['thread_id'])\n", + "runs = await client.runs.list(thread[\"thread_id\"])\n", "runs" ] }, @@ -148,11 +150,14 @@ "source": [ "# Helper function for formatting messages\n", "\n", + "\n", "def format_tool_calls(tool_calls):\n", " if tool_calls:\n", " formatted_calls = []\n", " for call in tool_calls:\n", - " formatted_calls.append(f\"Tool Call ID: {call['id']}, Function: {call['name']}, Arguments: {call['args']}\")\n", + " formatted_calls.append(\n", + " f\"Tool Call ID: {call['id']}, Function: {call['name']}, Arguments: {call['args']}\"\n", + " )\n", " return \"\\n\".join(formatted_calls)\n", " return \"No tool calls\"" ] @@ -1346,35 +1351,36 @@ "source": [ "input = {\"messages\": [{\"role\": \"user\", \"content\": \"whats the weather in sf\"}]}\n", "\n", - "async for event in client.runs.stream(thread['thread_id'], assistant['assistant_id'], input=input, stream_mode='messages'):\n", - " if event.event == 'metadata':\n", + "async for event in client.runs.stream(\n", + " thread[\"thread_id\"], assistant[\"assistant_id\"], input=input, stream_mode=\"messages\"\n", + "):\n", + " if event.event == \"metadata\":\n", " print(f\"Metadata: Run ID - {event.data['run_id']}\")\n", - " elif event.event == 'data':\n", + " elif event.event == \"data\":\n", " for data_item in event.data:\n", - " if 'role' in data_item and data_item['role'] == 'user':\n", + " if \"role\" in data_item and data_item[\"role\"] == \"user\":\n", " print(f\"Human: {data_item['content']}\")\n", " else:\n", - " tool_calls = data_item.get('tool_calls', [])\n", - " invalid_tool_calls = data_item.get('invalid_tool_calls', [])\n", - " content = data_item.get('content', \"\")\n", - " response_metadata = data_item.get('response_metadata', {})\n", + " tool_calls = data_item.get(\"tool_calls\", [])\n", + " invalid_tool_calls = data_item.get(\"invalid_tool_calls\", [])\n", + " content = data_item.get(\"content\", \"\")\n", + " response_metadata = data_item.get(\"response_metadata\", {})\n", "\n", " if content:\n", " print(f\"AI: {content}\")\n", - " \n", + "\n", " if tool_calls:\n", " print(\"Tool Calls:\")\n", " print(format_tool_calls(tool_calls))\n", - " \n", + "\n", " if invalid_tool_calls:\n", " print(\"Invalid Tool Calls:\")\n", " print(format_tool_calls(invalid_tool_calls))\n", "\n", " if response_metadata:\n", - " finish_reason = response_metadata.get('finish_reason', 'N/A')\n", + " finish_reason = response_metadata.get(\"finish_reason\", \"N/A\")\n", " print(f\"Response Metadata: Finish Reason - {finish_reason}\")\n", - " print(\"-\" * 50)\n", - " " + " print(\"-\" * 50)" ] } ], diff --git a/docs/docs/deploy/how_tos/stream_updates.ipynb b/docs/docs/deploy/how_tos/stream_updates.ipynb index 877194b53..81f61f5ab 100644 --- a/docs/docs/deploy/how_tos/stream_updates.ipynb +++ b/docs/docs/deploy/how_tos/stream_updates.ipynb @@ -62,7 +62,7 @@ "source": [ "# There should always be a default assistant with no configuration\n", "assistants = await client.assistants.search()\n", - "assistants = [a for a in assistants if not a['config']]\n", + "assistants = [a for a in assistants if not a[\"config\"]]\n", "assistants" ] }, @@ -136,7 +136,7 @@ } ], "source": [ - "runs = await client.runs.list(thread['thread_id'])\n", + "runs = await client.runs.list(thread[\"thread_id\"])\n", "runs" ] }, @@ -180,7 +180,12 @@ ], "source": [ "input = {\"messages\": [{\"role\": \"human\", \"content\": \"whats the weather in la\"}]}\n", - "async for chunk in client.runs.stream(thread['thread_id'], assistant['assistant_id'], input=input, stream_mode=\"updates\", ):\n", + "async for chunk in client.runs.stream(\n", + " thread[\"thread_id\"],\n", + " assistant[\"assistant_id\"],\n", + " input=input,\n", + " stream_mode=\"updates\",\n", + "):\n", " print(f\"Receiving new event of type: {chunk.event}...\")\n", " print(chunk.data)\n", " print(\"\\n\\n\")" diff --git a/docs/docs/deploy/how_tos/stream_values.ipynb b/docs/docs/deploy/how_tos/stream_values.ipynb index 86493758c..205ca5328 100644 --- a/docs/docs/deploy/how_tos/stream_values.ipynb +++ b/docs/docs/deploy/how_tos/stream_values.ipynb @@ -62,7 +62,7 @@ "source": [ "# There should always be a default assistant with no configuration\n", "assistants = await client.assistants.search()\n", - "assistants = [a for a in assistants if not a['config']]\n", + "assistants = [a for a in assistants if not a[\"config\"]]\n", "assistants" ] }, @@ -139,7 +139,9 @@ "source": [ "input = {\"messages\": [{\"role\": \"human\", \"content\": \"whats the weather in la\"}]}\n", "thread = await client.threads.create()\n", - "async for chunk in client.runs.stream(thread['thread_id'], assistant['assistant_id'], input=input):\n", + "async for chunk in client.runs.stream(\n", + " thread[\"thread_id\"], assistant[\"assistant_id\"], input=input\n", + "):\n", " print(f\"Receiving new event of type: {chunk.event}...\")\n", " print(chunk.data)\n", " print(\"\\n\\n\")" @@ -163,7 +165,9 @@ "input = {\"messages\": [{\"role\": \"human\", \"content\": \"whats the weather in la\"}]}\n", "thread = await client.threads.create()\n", "final_answer = None\n", - "async for chunk in client.runs.stream(thread['thread_id'], assistant['assistant_id'], input=input):\n", + "async for chunk in client.runs.stream(\n", + " thread[\"thread_id\"], assistant[\"assistant_id\"], input=input\n", + "):\n", " if chunk.event == \"values\":\n", " final_answer = chunk.data" ] diff --git a/examples/learning.ipynb b/examples/learning.ipynb index 1f00937a3..7644b07f2 100644 --- a/examples/learning.ipynb +++ b/examples/learning.ipynb @@ -475,9 +475,9 @@ "metadata": {}, "outputs": [], "source": [ - "current_values.values[\"messages\"][-1].tool_calls[0][\"args\"][\n", - " \"query\"\n", - "] = \"weather in San Francisco, Accuweather\"" + "current_values.values[\"messages\"][-1].tool_calls[0][\"args\"][\"query\"] = (\n", + " \"weather in San Francisco, Accuweather\"\n", + ")" ] }, { diff --git a/examples/time-travel.ipynb b/examples/time-travel.ipynb index 244f48681..c260fe201 100644 --- a/examples/time-travel.ipynb +++ b/examples/time-travel.ipynb @@ -729,9 +729,9 @@ "metadata": {}, "outputs": [], "source": [ - "current_values.values[\"messages\"][-1].tool_calls[0][\"args\"][\n", - " \"query\"\n", - "] = \"weather in San Francisco today\"" + "current_values.values[\"messages\"][-1].tool_calls[0][\"args\"][\"query\"] = (\n", + " \"weather in San Francisco today\"\n", + ")" ] }, { diff --git a/examples/tutorials/sql-agent.ipynb b/examples/tutorials/sql-agent.ipynb index 3c1555616..b3946b9d0 100644 --- a/examples/tutorials/sql-agent.ipynb +++ b/examples/tutorials/sql-agent.ipynb @@ -43,11 +43,11 @@ "execution_count": 1, "id": "6c05a600f1afb5b6", "metadata": { - "collapsed": false, "ExecuteTime": { "end_time": "2024-06-12T21:24:00.532147Z", "start_time": "2024-06-12T21:24:00.526043Z" - } + }, + "collapsed": false }, "outputs": [], "source": [ @@ -78,11 +78,11 @@ "execution_count": 2, "id": "64b0bf1b14c2e902", "metadata": { - "collapsed": false, "ExecuteTime": { "end_time": "2024-06-12T21:24:09.918436Z", "start_time": "2024-06-12T21:24:09.608563Z" - } + }, + "collapsed": false }, "outputs": [ { @@ -125,11 +125,11 @@ "execution_count": 3, "id": "a60191bd3489f278", "metadata": { - "collapsed": false, "ExecuteTime": { "end_time": "2024-06-12T21:24:14.663745Z", "start_time": "2024-06-12T21:24:13.527958Z" - } + }, + "collapsed": false }, "outputs": [], "source": [ @@ -142,11 +142,11 @@ "execution_count": 4, "id": "1f1e1f4f86ed54", "metadata": { - "collapsed": false, "ExecuteTime": { "end_time": "2024-06-12T21:24:15.891582Z", "start_time": "2024-06-12T21:24:15.289782Z" - } + }, + "collapsed": false }, "outputs": [ { @@ -192,11 +192,11 @@ "execution_count": 5, "id": "deae8460e4cf72b1", "metadata": { - "collapsed": false, "ExecuteTime": { "end_time": "2024-06-12T21:24:17.557848Z", "start_time": "2024-06-12T21:24:17.508550Z" - } + }, + "collapsed": false }, "outputs": [], "source": [ @@ -214,6 +214,7 @@ " [RunnableLambda(handle_tool_error)], exception_key=\"error\"\n", " )\n", "\n", + "\n", "def handle_tool_error(state) -> dict:\n", " error = state.get(\"error\")\n", " tool_calls = state[\"messages\"][-1].tool_calls\n", @@ -341,6 +342,7 @@ " return \"Error: Query failed. Please rewrite your query and try again.\"\n", " return result\n", "\n", + "\n", "print(db_query_tool.invoke(\"SELECT * FROM Artist LIMIT 10;\"))" ] }, @@ -393,8 +395,12 @@ "\n", "You will call the appropriate tool to execute the query after running this check.\"\"\"\n", "\n", - "query_check_prompt = ChatPromptTemplate.from_messages([(\"system\", query_check_system),(\"placeholder\", \"{messages}\")])\n", - "query_check = query_check_prompt | ChatOpenAI(model=\"gpt-4o\", temperature=0).bind_tools([db_query_tool], tool_choice=\"required\")\n", + "query_check_prompt = ChatPromptTemplate.from_messages(\n", + " [(\"system\", query_check_system), (\"placeholder\", \"{messages}\")]\n", + ")\n", + "query_check = query_check_prompt | ChatOpenAI(model=\"gpt-4o\", temperature=0).bind_tools(\n", + " [db_query_tool], tool_choice=\"required\"\n", + ")\n", "\n", "query_check.invoke({\"messages\": [(\"user\", \"SELET * FROM Artist LIMIT 10;\")]})" ] @@ -440,9 +446,11 @@ "class State(TypedDict):\n", " messages: Annotated[list[AnyMessage], add_messages]\n", "\n", + "\n", "# Define a new graph\n", "workflow = StateGraph(State)\n", "\n", + "\n", "# Add a node for the first tool call\n", "def first_tool_call(state: State) -> dict[str, list[AIMessage]]:\n", " return {\n", @@ -452,8 +460,7 @@ " tool_calls=[\n", " {\n", " \"name\": \"sql_db_list_tables\",\n", - " \"args\": {\n", - " },\n", + " \"args\": {},\n", " \"id\": \"tool_abcd123\",\n", " }\n", " ],\n", @@ -461,31 +468,41 @@ " ]\n", " }\n", "\n", + "\n", "def model_check_query(state: State) -> dict[str, list[AIMessage]]:\n", " \"\"\"\n", " Use this tool to double-check if your query is correct before executing it.\n", " \"\"\"\n", - " return {\n", - " \"messages\": [\n", - " query_check.invoke({\"messages\": [state[\"messages\"][-1]]})\n", - " ]\n", - " }\n", + " return {\"messages\": [query_check.invoke({\"messages\": [state[\"messages\"][-1]]})]}\n", + "\n", "\n", "workflow.add_node(\"first_tool_call\", first_tool_call)\n", "\n", "# Add nodes for the first two tools\n", - "workflow.add_node(\"list_tables_tool\", create_tool_node_with_fallback([list_tables_tool]))\n", + "workflow.add_node(\n", + " \"list_tables_tool\", create_tool_node_with_fallback([list_tables_tool])\n", + ")\n", "workflow.add_node(\"get_schema_tool\", create_tool_node_with_fallback([get_schema_tool]))\n", "\n", "# Add a node for a model to choose the relevant tables based on the question and available tables\n", - "model_get_schema = ChatOpenAI(model=\"gpt-4o\", temperature=0).bind_tools([get_schema_tool])\n", - "workflow.add_node(\"model_get_schema\", lambda state: {\"messages\": [model_get_schema.invoke(state[\"messages\"])],})\n", + "model_get_schema = ChatOpenAI(model=\"gpt-4o\", temperature=0).bind_tools(\n", + " [get_schema_tool]\n", + ")\n", + "workflow.add_node(\n", + " \"model_get_schema\",\n", + " lambda state: {\n", + " \"messages\": [model_get_schema.invoke(state[\"messages\"])],\n", + " },\n", + ")\n", + "\n", "\n", "# Describe a tool to represent the end state\n", "class SubmitFinalAnswer(BaseModel):\n", " \"\"\"Submit the final answer to the user based on the query results.\"\"\"\n", + "\n", " final_answer: str = Field(..., description=\"The final answer to the user\")\n", "\n", + "\n", "# Add a node for a model to generate a query based on the question and schema\n", "query_gen_system = \"\"\"You are a SQL expert with a strong attention to detail.\n", "\n", @@ -509,11 +526,17 @@ "If you have enough information to answer the input question, simply invoke the appropriate tool to submit the final answer to the user.\n", "\n", "DO NOT make any DML statements (INSERT, UPDATE, DELETE, DROP etc.) to the database.\"\"\"\n", - "query_gen_prompt = ChatPromptTemplate.from_messages([(\"system\", query_gen_system),(\"placeholder\", \"{messages}\")])\n", - "query_gen = query_gen_prompt | ChatOpenAI(model=\"gpt-4o\", temperature=0).bind_tools([SubmitFinalAnswer])\n", + "query_gen_prompt = ChatPromptTemplate.from_messages(\n", + " [(\"system\", query_gen_system), (\"placeholder\", \"{messages}\")]\n", + ")\n", + "query_gen = query_gen_prompt | ChatOpenAI(model=\"gpt-4o\", temperature=0).bind_tools(\n", + " [SubmitFinalAnswer]\n", + ")\n", + "\n", + "\n", "def query_gen_node(state: State):\n", " message = query_gen.invoke(state)\n", - " \n", + "\n", " # Sometimes, the LLM will hallucinate and call the wrong tool. We need to catch this and return an error message.\n", " tool_messages = []\n", " if message.tool_calls:\n", @@ -529,6 +552,7 @@ " tool_messages = []\n", " return {\"messages\": [message] + tool_messages}\n", "\n", + "\n", "workflow.add_node(\"query_gen\", query_gen_node)\n", "\n", "# Add a node for the model to check the query before executing it\n", @@ -537,6 +561,7 @@ "# Add node for executing the query\n", "workflow.add_node(\"execute_query\", create_tool_node_with_fallback([db_query_tool]))\n", "\n", + "\n", "# Define a conditional edge to decide whether to continue or end the workflow\n", "def should_continue(state: State) -> Literal[END, \"correct_query\", \"query_gen\"]:\n", " messages = state[\"messages\"]\n", @@ -549,6 +574,7 @@ " else:\n", " return \"correct_query\"\n", "\n", + "\n", "# Specify the edges between the nodes\n", "workflow.set_entry_point(\"first_tool_call\")\n", "workflow.add_edge(\"first_tool_call\", \"list_tables_tool\")\n", @@ -649,7 +675,9 @@ } ], "source": [ - "for event in app.stream({\"messages\": [(\"user\", \"Which sales agent made the most in sales in 2009?\")]}):\n", + "for event in app.stream(\n", + " {\"messages\": [(\"user\", \"Which sales agent made the most in sales in 2009?\")]}\n", + "):\n", " print(event)" ] } diff --git a/langgraph/graph/graph.py b/langgraph/graph/graph.py index e8c281bdc..4448d23a1 100644 --- a/langgraph/graph/graph.py +++ b/langgraph/graph/graph.py @@ -125,12 +125,10 @@ class Graph: return self.edges @overload - def add_node(self, node: RunnableLike) -> None: - ... + def add_node(self, node: RunnableLike) -> None: ... @overload - def add_node(self, node: str, action: RunnableLike) -> None: - ... + def add_node(self, node: str, action: RunnableLike) -> None: ... def add_node( self, node: Union[str, RunnableLike], action: Optional[RunnableLike] = None diff --git a/langgraph/managed/base.py b/langgraph/managed/base.py index b06f6a7c7..a41fb980b 100644 --- a/langgraph/managed/base.py +++ b/langgraph/managed/base.py @@ -63,8 +63,7 @@ class ManagedValue(ABC, Generic[V]): pass @abstractmethod - def __call__(self, step: int, task: PregelTaskDescription) -> V: - ... + def __call__(self, step: int, task: PregelTaskDescription) -> V: ... class ConfiguredManagedValue(NamedTuple): diff --git a/langgraph/prebuilt/__init__.py b/langgraph/prebuilt/__init__.py index b05e0e660..5d7501bed 100644 --- a/langgraph/prebuilt/__init__.py +++ b/langgraph/prebuilt/__init__.py @@ -1,4 +1,5 @@ """langgraph.prebuilt exposes a higher-level API for creating and executing agents and tools.""" + from langgraph.prebuilt import chat_agent_executor from langgraph.prebuilt.agent_executor import create_agent_executor from langgraph.prebuilt.chat_agent_executor import create_react_agent diff --git a/langgraph/pregel/__init__.py b/langgraph/pregel/__init__.py index 4d53c6be9..19e6d8b82 100644 --- a/langgraph/pregel/__init__.py +++ b/langgraph/pregel/__init__.py @@ -126,8 +126,7 @@ class Channel: *, key: Optional[str] = None, tags: Optional[list[str]] = None, - ) -> PregelNode: - ... + ) -> PregelNode: ... @overload @classmethod @@ -137,8 +136,7 @@ class Channel: *, key: None = None, tags: Optional[list[str]] = None, - ) -> PregelNode: - ... + ) -> PregelNode: ... @classmethod def subscribe_to( @@ -1609,8 +1607,7 @@ def _prepare_next_tasks( step: int, for_execution: Literal[False], manager: Literal[None] = None, -) -> tuple[Checkpoint, list[PregelTaskDescription]]: - ... +) -> tuple[Checkpoint, list[PregelTaskDescription]]: ... @overload @@ -1623,8 +1620,7 @@ def _prepare_next_tasks( step: int, for_execution: Literal[True], manager: Union[ParentRunManager, AsyncParentRunManager], -) -> tuple[Checkpoint, list[PregelExecutableTask]]: - ... +) -> tuple[Checkpoint, list[PregelExecutableTask]]: ... def _prepare_next_tasks( diff --git a/langgraph/pregel/retry.py b/langgraph/pregel/retry.py index 6ec224012..6dcfc306c 100644 --- a/langgraph/pregel/retry.py +++ b/langgraph/pregel/retry.py @@ -51,9 +51,9 @@ class RetryPolicy(NamedTuple): """Maximum number of attempts to make before giving up, including the first.""" jitter: bool = True """Whether to add random jitter to the interval between retries.""" - retry_on: Union[ - tuple[Exception, ...], Callable[[Exception], bool] - ] = default_retry_on + retry_on: Union[tuple[Exception, ...], Callable[[Exception], bool]] = ( + default_retry_on + ) """List of exceptions that should trigger a retry, or a callable that returns True for exceptions that should trigger a retry.""" diff --git a/langgraph/serde/base.py b/langgraph/serde/base.py index 2fbb0ab71..5f1250d1e 100644 --- a/langgraph/serde/base.py +++ b/langgraph/serde/base.py @@ -10,8 +10,6 @@ class SerializerProtocol(Protocol): Valid implementations include the `pickle`, `json` and `orjson` modules. """ - def dumps(self, obj: Any) -> bytes: - ... + def dumps(self, obj: Any) -> bytes: ... - def loads(self, data: bytes) -> Any: - ... + def loads(self, data: bytes) -> Any: ...