From 704da81b5d534da39929ea73bd6e597942da86fc Mon Sep 17 00:00:00 2001 From: isaac hershenson Date: Tue, 18 Jun 2024 15:00:30 -0700 Subject: [PATCH] Revert "fmt" This reverts commit ec8fca977ecd9de9259addd68f65f2f2fcdfdb70. --- 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, 125 insertions(+), 202 deletions(-) diff --git a/docs/docs/deploy/how_tos/background_run.ipynb b/docs/docs/deploy/how_tos/background_run.ipynb index 52e2f50cb..87efa3a0b 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,9 +138,7 @@ "source": [ "# Let's kick off a run\n", "input = {\"messages\": [{\"role\": \"human\", \"content\": \"whats the weather in sf\"}]}\n", - "run = await client.runs.create(\n", - " thread[\"thread_id\"], assistant[\"assistant_id\"], input=input\n", - ")" + "run = await client.runs.create(thread['thread_id'], assistant[\"assistant_id\"], input=input)\n" ] }, { @@ -168,7 +166,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'])" ] }, { @@ -451,7 +449,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'])" ] }, { @@ -479,7 +477,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'])" ] }, { @@ -490,7 +488,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'])" ] }, { @@ -591,7 +589,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 e8f00027f..3d427bd0d 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,12 +93,10 @@ ], "source": [ "# We can now call `.get_schemas` to get schemas associated with this graph\n", - "schemas = await client.assistants.get_schemas(\n", - " assistant_id=base_assistant[\"assistant_id\"]\n", - ")\n", + "schemas = await client.assistants.get_schemas(assistant_id=base_assistant[\"assistant_id\"])\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']" ] }, { @@ -108,9 +106,7 @@ "metadata": {}, "outputs": [], "source": [ - "assistant = await client.assistants.create(\n", - " graph_id=\"agent\", config={\"configurable\": {\"model_name\": \"openai\"}}\n", - ")" + "assistant = await client.assistants.create(graph_id=\"agent\", config={\"configurable\": {\"model_name\": \"openai\"}})" ] }, { @@ -167,9 +163,7 @@ "source": [ "thread = await client.threads.create()\n", "input = {\"messages\": [{\"role\": \"user\", \"content\": \"who made you?\"}]}\n", - "async for event in client.runs.stream(\n", - " thread[\"thread_id\"], assistant[\"assistant_id\"], input=input\n", - "):\n", + "async for event in client.runs.stream(thread['thread_id'], assistant['assistant_id'], input=input):\n", " print(event)" ] }, diff --git a/docs/docs/deploy/how_tos/double_texting.ipynb b/docs/docs/deploy/how_tos/double_texting.ipynb index e4c90f12c..b5862eb85 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": [ - "import httpx\n", + "from langgraph_sdk import get_client\n", "from langchain_core.messages import convert_to_messages\n", - "from langgraph_sdk import get_client" + "import httpx" ] }, { @@ -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,8 +222,7 @@ "source": [ "# the first run will be interrupted\n", "interrupted_run = await client.runs.create(\n", - " thread[\"thread_id\"],\n", - " assistant[\"assistant_id\"],\n", + " thread[\"thread_id\"], assistant[\"assistant_id\"],\n", " input={\"messages\": [{\"role\": \"human\", \"content\": \"whats the weather in sf?\"}]},\n", ")\n", "await asyncio.sleep(2)\n", @@ -378,8 +377,7 @@ "source": [ "# the first run will be interrupted\n", "rolled_back_run = await client.runs.create(\n", - " thread[\"thread_id\"],\n", - " assistant[\"assistant_id\"],\n", + " thread[\"thread_id\"], assistant[\"assistant_id\"],\n", " input={\"messages\": [{\"role\": \"human\", \"content\": \"whats the weather in sf?\"}]},\n", ")\n", "await asyncio.sleep(2)\n", @@ -481,7 +479,7 @@ "source": [ "try:\n", " await client.runs.get(thread[\"thread_id\"], rolled_back_run[\"run_id\"])\n", - "except httpx.HTTPStatusError as _:\n", + "except httpx.HTTPStatusError as e:\n", " print(\"Original run was correctly deleted\")" ] }, @@ -514,7 +512,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 447d144e7..9ab91a93f 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,11 +188,7 @@ "source": [ "input = {\"messages\": [{\"role\": \"human\", \"content\": \"whats the weather in sf\"}]}\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", + " thread['thread_id'], assistant['assistant_id'], input=input, stream_mode=\"updates\", interrupt_before=['action']\n", "):\n", " print(f\"Receiving new event of type: {chunk.event}...\")\n", " print(chunk.data)\n", @@ -243,11 +239,7 @@ "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", + " thread['thread_id'], assistant['assistant_id'], input=input, stream_mode=\"updates\", interrupt_before=['action']\n", "):\n", " print(f\"Receiving new event of type: {chunk.event}...\")\n", " print(chunk.data)\n", @@ -297,11 +289,7 @@ "source": [ "input = {\"messages\": [{\"role\": \"human\", \"content\": \"whats the weather in la?\"}]}\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", + " thread['thread_id'], assistant['assistant_id'], input=input, stream_mode=\"updates\", interrupt_before=['action']\n", "):\n", " print(f\"Receiving new event of type: {chunk.event}...\")\n", " print(chunk.data)\n", @@ -323,7 +311,7 @@ "metadata": {}, "outputs": [], "source": [ - "thread_state = await client.threads.get_state(thread[\"thread_id\"])" + "thread_state = await client.threads.get_state(thread['thread_id'])" ] }, { @@ -341,7 +329,7 @@ "metadata": {}, "outputs": [], "source": [ - "last_message = thread_state[\"values\"][\"messages\"][-1]" + "last_message = thread_state['values']['messages'][-1]" ] }, { @@ -365,7 +353,7 @@ } ], "source": [ - "last_message[\"content\"]" + "last_message['content']" ] }, { @@ -383,14 +371,12 @@ "metadata": {}, "outputs": [], "source": [ - "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['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['content'] = [{\n", "# 'id': last_message['content'][0]['id'],\n", "# 'name': 'tavily_search_results_json',\n", @@ -427,9 +413,7 @@ } ], "source": [ - "await client.threads.update_state(\n", - " thread[\"thread_id\"], values={\"messages\": [last_message]}\n", - ")" + "await client.threads.update_state(thread['thread_id'], values={\"messages\": [last_message]})" ] }, { @@ -460,8 +444,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']" ] }, { @@ -508,11 +492,7 @@ "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", + " thread['thread_id'], assistant['assistant_id'], input=input, stream_mode=\"updates\", interrupt_before=['action']\n", "):\n", " print(f\"Receiving new event of type: {chunk.event}...\")\n", " print(chunk.data)\n", @@ -537,7 +517,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)" ] }, { @@ -591,7 +571,7 @@ ], "source": [ "rewind_state = thread_history[3]\n", - "rewind_state[\"values\"][\"messages\"][-1][\"tool_calls\"]" + "rewind_state['values']['messages'][-1]['tool_calls']" ] }, { @@ -613,7 +593,7 @@ } ], "source": [ - "rewind_state[\"config\"]" + "rewind_state['config']" ] }, { @@ -660,12 +640,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 077ac4417..94d08a04e 100644 --- a/docs/docs/deploy/how_tos/same-thread.ipynb +++ b/docs/docs/deploy/how_tos/same-thread.ipynb @@ -23,13 +23,11 @@ "\n", "client = get_client()\n", "\n", - "openai_assistant = await client.assistants.create(\n", - " graph_id=\"agent\", config={\"configurable\": {\"model_name\": \"openai\"}}\n", - ")\n", + "openai_assistant = await client.assistants.create(graph_id=\"agent\", config={\"configurable\": {\"model_name\": \"openai\"}})\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]" ] }, { @@ -119,12 +117,7 @@ "source": [ "thread = await client.threads.create()\n", "input = {\"messages\": [{\"role\": \"user\", \"content\": \"who made you?\"}]}\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", + "async for event in client.runs.stream(thread['thread_id'], openai_assistant['assistant_id'], input=input, stream_mode='updates'):\n", " print(event)" ] }, @@ -154,12 +147,7 @@ ], "source": [ "input = {\"messages\": [{\"role\": \"user\", \"content\": \"and you?\"}]}\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", + "async for event in client.runs.stream(thread['thread_id'], default_assistant['assistant_id'], input=input, stream_mode='updates'):\n", " print(event)" ] }, diff --git a/docs/docs/deploy/how_tos/stream_messages.ipynb b/docs/docs/deploy/how_tos/stream_messages.ipynb index ede2e7d4e..60439088d 100644 --- a/docs/docs/deploy/how_tos/stream_messages.ipynb +++ b/docs/docs/deploy/how_tos/stream_messages.ipynb @@ -63,9 +63,7 @@ "metadata": {}, "outputs": [], "source": [ - "assistant = await client.assistants.create(\n", - " graph_id=\"agent\", config={\"configurable\": {\"model_name\": \"openai\"}}\n", - ")" + "assistant = await client.assistants.create(graph_id=\"agent\", config={\"configurable\": {\"model_name\": \"openai\"}})" ] }, { @@ -137,7 +135,7 @@ } ], "source": [ - "runs = await client.runs.list(thread[\"thread_id\"])\n", + "runs = await client.runs.list(thread['thread_id'])\n", "runs" ] }, @@ -150,14 +148,11 @@ "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(\n", - " f\"Tool Call ID: {call['id']}, Function: {call['name']}, Arguments: {call['args']}\"\n", - " )\n", + " formatted_calls.append(f\"Tool Call ID: {call['id']}, Function: {call['name']}, Arguments: {call['args']}\")\n", " return \"\\n\".join(formatted_calls)\n", " return \"No tool calls\"" ] @@ -1351,36 +1346,35 @@ "source": [ "input = {\"messages\": [{\"role\": \"user\", \"content\": \"whats the weather in sf\"}]}\n", "\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", + "async for event in client.runs.stream(thread['thread_id'], assistant['assistant_id'], input=input, stream_mode='messages'):\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)" + " print(\"-\" * 50)\n", + " " ] } ], diff --git a/docs/docs/deploy/how_tos/stream_updates.ipynb b/docs/docs/deploy/how_tos/stream_updates.ipynb index 81f61f5ab..877194b53 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,12 +180,7 @@ ], "source": [ "input = {\"messages\": [{\"role\": \"human\", \"content\": \"whats the weather in la\"}]}\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", + "async for chunk in client.runs.stream(thread['thread_id'], assistant['assistant_id'], input=input, stream_mode=\"updates\", ):\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 205ca5328..86493758c 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,9 +139,7 @@ "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(\n", - " thread[\"thread_id\"], assistant[\"assistant_id\"], input=input\n", - "):\n", + "async for chunk in client.runs.stream(thread['thread_id'], assistant['assistant_id'], input=input):\n", " print(f\"Receiving new event of type: {chunk.event}...\")\n", " print(chunk.data)\n", " print(\"\\n\\n\")" @@ -165,9 +163,7 @@ "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(\n", - " thread[\"thread_id\"], assistant[\"assistant_id\"], input=input\n", - "):\n", + "async for chunk in client.runs.stream(thread['thread_id'], assistant['assistant_id'], input=input):\n", " if chunk.event == \"values\":\n", " final_answer = chunk.data" ] diff --git a/examples/learning.ipynb b/examples/learning.ipynb index 7644b07f2..1f00937a3 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\"][\"query\"] = (\n", - " \"weather in San Francisco, Accuweather\"\n", - ")" + "current_values.values[\"messages\"][-1].tool_calls[0][\"args\"][\n", + " \"query\"\n", + "] = \"weather in San Francisco, Accuweather\"" ] }, { diff --git a/examples/time-travel.ipynb b/examples/time-travel.ipynb index c260fe201..244f48681 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\"][\"query\"] = (\n", - " \"weather in San Francisco today\"\n", - ")" + "current_values.values[\"messages\"][-1].tool_calls[0][\"args\"][\n", + " \"query\"\n", + "] = \"weather in San Francisco today\"" ] }, { diff --git a/examples/tutorials/sql-agent.ipynb b/examples/tutorials/sql-agent.ipynb index b3946b9d0..3c1555616 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,7 +214,6 @@ " [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", @@ -342,7 +341,6 @@ " 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;\"))" ] }, @@ -395,12 +393,8 @@ "\n", "You will call the appropriate tool to execute the query after running this check.\"\"\"\n", "\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", + "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", "\n", "query_check.invoke({\"messages\": [(\"user\", \"SELET * FROM Artist LIMIT 10;\")]})" ] @@ -446,11 +440,9 @@ "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", @@ -460,7 +452,8 @@ " tool_calls=[\n", " {\n", " \"name\": \"sql_db_list_tables\",\n", - " \"args\": {},\n", + " \"args\": {\n", + " },\n", " \"id\": \"tool_abcd123\",\n", " }\n", " ],\n", @@ -468,41 +461,31 @@ " ]\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 {\"messages\": [query_check.invoke({\"messages\": [state[\"messages\"][-1]]})]}\n", - "\n", + " return {\n", + " \"messages\": [\n", + " query_check.invoke({\"messages\": [state[\"messages\"][-1]]})\n", + " ]\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(\n", - " \"list_tables_tool\", create_tool_node_with_fallback([list_tables_tool])\n", - ")\n", + "workflow.add_node(\"list_tables_tool\", create_tool_node_with_fallback([list_tables_tool]))\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(\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", + "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", "\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", @@ -526,17 +509,11 @@ "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(\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", + "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", "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", @@ -552,7 +529,6 @@ " 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", @@ -561,7 +537,6 @@ "# 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", @@ -574,7 +549,6 @@ " 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", @@ -675,9 +649,7 @@ } ], "source": [ - "for event in app.stream(\n", - " {\"messages\": [(\"user\", \"Which sales agent made the most in sales in 2009?\")]}\n", - "):\n", + "for event in app.stream({\"messages\": [(\"user\", \"Which sales agent made the most in sales in 2009?\")]}):\n", " print(event)" ] } diff --git a/langgraph/graph/graph.py b/langgraph/graph/graph.py index 4448d23a1..e8c281bdc 100644 --- a/langgraph/graph/graph.py +++ b/langgraph/graph/graph.py @@ -125,10 +125,12 @@ 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 a41fb980b..b06f6a7c7 100644 --- a/langgraph/managed/base.py +++ b/langgraph/managed/base.py @@ -63,7 +63,8 @@ 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 5d7501bed..b05e0e660 100644 --- a/langgraph/prebuilt/__init__.py +++ b/langgraph/prebuilt/__init__.py @@ -1,5 +1,4 @@ """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 19e6d8b82..4d53c6be9 100644 --- a/langgraph/pregel/__init__.py +++ b/langgraph/pregel/__init__.py @@ -126,7 +126,8 @@ class Channel: *, key: Optional[str] = None, tags: Optional[list[str]] = None, - ) -> PregelNode: ... + ) -> PregelNode: + ... @overload @classmethod @@ -136,7 +137,8 @@ class Channel: *, key: None = None, tags: Optional[list[str]] = None, - ) -> PregelNode: ... + ) -> PregelNode: + ... @classmethod def subscribe_to( @@ -1607,7 +1609,8 @@ def _prepare_next_tasks( step: int, for_execution: Literal[False], manager: Literal[None] = None, -) -> tuple[Checkpoint, list[PregelTaskDescription]]: ... +) -> tuple[Checkpoint, list[PregelTaskDescription]]: + ... @overload @@ -1620,7 +1623,8 @@ 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 6dcfc306c..6ec224012 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 5f1250d1e..2fbb0ab71 100644 --- a/langgraph/serde/base.py +++ b/langgraph/serde/base.py @@ -10,6 +10,8 @@ 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: + ...