From 925d01533536d5cdf44b2fcceb82e692d64071c8 Mon Sep 17 00:00:00 2001 From: William Fu-Hinthorn <13333726+hinthornw@users.noreply.github.com> Date: Mon, 12 Feb 2024 15:05:45 -0800 Subject: [PATCH] Update llmcompiler --- examples/llm-compiler/LLMCompiler.ipynb | 264 +++++++++++------- .../plan-and-execute/plan-and-execute.ipynb | 60 ++-- examples/rewoo/rewoo.ipynb | 4 +- 3 files changed, 211 insertions(+), 117 deletions(-) diff --git a/examples/llm-compiler/LLMCompiler.ipynb b/examples/llm-compiler/LLMCompiler.ipynb index 3aedf4aea..676e12492 100644 --- a/examples/llm-compiler/LLMCompiler.ipynb +++ b/examples/llm-compiler/LLMCompiler.ipynb @@ -9,16 +9,18 @@ "\n", "This notebook shows how to implement [LLMCompiler, by Kim, et. al](https://arxiv.org/abs/2312.04511) in LangGraph.\n", "\n", + "LLMCompiler is an agent architecture designed to **speed up** the execution of agentic tasks by eagerly-executed tasks within a DAG. It also saves costs on redundant token usage by reducing the number of calls to the LLM. Below is an overview of its computational graph:\n", + "\n", "![LLMCompiler Graph](./img/llm-compiler.png)\n", "\n", - "LLMCompiler is an agent architecture designed to speed up the execution of agentic tasks by eagerly-executed tasks within a DAG. It has 3 main components:\n", + "It has 3 main components:\n", "\n", "1. Planner: stream a DAG of tasks.\n", "2. Task Fetching Unit: schedules and executes the tasks as soon as they are executable\n", "3. Joiner: Responds to the user or triggers a second plan\n", "\n", "\n", - "This notebook walks through each component and shows how to wire them together using LangGraph. \n", + "This notebook walks through each component and shows how to wire them together using LangGraph. The end result will leave a trace [like the following](https://smith.langchain.com/public/218c2677-c719-4147-b0e9-7bc3b5bb2623/r).\n", "\n", "\n", "**First,** install the dependencies, and set up LangSmith for tracing to more easily debug and observe the agent." @@ -36,7 +38,7 @@ }, { "cell_type": "code", - "execution_count": 41, + "execution_count": 1, "id": "abbd6948-e9a3-47ca-89c7-7ac2fc5eca8b", "metadata": {}, "outputs": [], @@ -44,9 +46,12 @@ "import os\n", "import getpass\n", "\n", + "\n", "def _get_pass(var: str):\n", " if var not in os.environ:\n", " os.environ[var] = getpass.getpass(f\"{var}: \")\n", + "\n", + "\n", "# Optional: Debug + trace calls using LangSmith\n", "os.environ[\"LANGCHAIN_TRACING_V2\"] = \"True\"\n", "os.environ[\"LANGCHAIN_PROJECT\"] = \"LLMCompiler\"\n", @@ -68,27 +73,31 @@ }, { "cell_type": "code", - "execution_count": 42, + "execution_count": 3, "id": "e7476bb2-1a51-42f6-b7ae-82a0300bbf84", "metadata": {}, "outputs": [], "source": [ "from langchain_openai import ChatOpenAI\n", "from langchain_community.tools.tavily_search import TavilySearchResults\n", + "\n", "# Imported from the https://github.com/langchain-ai/langgraph/tree/main/examples/plan-and-execute repo\n", "from math_tools import get_math_tool\n", "\n", "_get_pass(\"TAVILY_API_KEY\")\n", "\n", "calculate = get_math_tool(ChatOpenAI(model=\"gpt-4-turbo-preview\"))\n", - "search = TavilySearchResults(max_results=1, description='tavily_search_results_json(query=\"the search query\") - a search engine.')\n", + "search = TavilySearchResults(\n", + " max_results=1,\n", + " description='tavily_search_results_json(query=\"the search query\") - a search engine.',\n", + ")\n", "\n", "tools = [search, calculate]" ] }, { "cell_type": "code", - "execution_count": 43, + "execution_count": 4, "id": "152eecf3-6bef-4718-af71-a0b3c5a3b009", "metadata": {}, "outputs": [ @@ -98,13 +107,18 @@ "'37'" ] }, - "execution_count": 43, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "calculate.invoke({\"problem\": \"What's the temp of sf + 5?\", \"context\": [\"Thet empreature of sf is 32 degrees\"]})" + "calculate.invoke(\n", + " {\n", + " \"problem\": \"What's the temp of sf + 5?\",\n", + " \"context\": [\"Thet empreature of sf is 32 degrees\"],\n", + " }\n", + ")" ] }, { @@ -133,7 +147,7 @@ }, { "cell_type": "code", - "execution_count": 44, + "execution_count": 5, "id": "15dd9639-691f-4906-9012-83fd6e9ac126", "metadata": {}, "outputs": [ @@ -181,7 +195,12 @@ "from langchain_core.prompts import ChatPromptTemplate\n", "from langchain_core.runnables import RunnableBranch\n", "from langchain_core.tools import BaseTool\n", - "from langchain_core.messages import BaseMessage, FunctionMessage, HumanMessage, SystemMessage\n", + "from langchain_core.messages import (\n", + " BaseMessage,\n", + " FunctionMessage,\n", + " HumanMessage,\n", + " SystemMessage,\n", + ")\n", "\n", "from output_parser import LLMCompilerPlanParser, Task\n", "from langchain import hub\n", @@ -194,12 +213,14 @@ }, { "cell_type": "code", - "execution_count": 45, + "execution_count": 6, "id": "45689d40-d8df-4316-a121-6ea9c87d2efe", "metadata": {}, "outputs": [], "source": [ - "def create_planner(llm: BaseChatModel, tools: Sequence[BaseTool], base_prompt: ChatPromptTemplate):\n", + "def create_planner(\n", + " llm: BaseChatModel, tools: Sequence[BaseTool], base_prompt: ChatPromptTemplate\n", + "):\n", " tool_descriptions = \"\\n\".join(\n", " f\"{i}. {tool.description}\\n\" for i, tool in enumerate(tools)\n", " )\n", @@ -218,7 +239,7 @@ " num_tools=len(tools),\n", " tool_descriptions=tool_descriptions,\n", " )\n", - " \n", + "\n", " def should_replan(state: list):\n", " # Context is passed as a system message\n", " return isinstance(state[-1], SystemMessage)\n", @@ -234,7 +255,7 @@ " break\n", " state[-1].content = state[-1].content + f\" - Begin counting at : {next_task}\"\n", " return {\"messages\": state}\n", - " \n", + "\n", " return (\n", " RunnableBranch(\n", " (should_replan, wrap_and_get_last_index | replanner_prompt),\n", @@ -247,7 +268,7 @@ }, { "cell_type": "code", - "execution_count": 46, + "execution_count": 7, "id": "bbdcb57b-5362-4b9e-88db-fb3fae443fb0", "metadata": {}, "outputs": [], @@ -259,7 +280,7 @@ }, { "cell_type": "code", - "execution_count": 47, + "execution_count": 8, "id": "730490c6-6e3a-4173-82a1-9eb9d5eeff20", "metadata": {}, "outputs": [ @@ -269,7 +290,7 @@ "text": [ "description='tavily_search_results_json(query=\"the search query\") - a search engine.' max_results=1 {'query': 'current temperature in San Francisco'}\n", "---\n", - "name='math' description='math(problem: str, context: Optional[List[str]] = None, config: Optional[langchain_core.runnables.config.RunnableConfig] = None) - math(problem: str, context: Optional[list[str]]) -> float:\\n - Solves the provided math problem.\\n - `problem` can be either a simple math problem (e.g. \"1 + 3\") or a word problem (e.g. \"how many apples are there if there are 3 apples and 2 apples\").\\n - You cannot calculate multiple expressions in one call. For instance, `math(\\'1 + 3, 2 + 4\\')` does not work. If you need to calculate multiple expressions, you need to call them separately like `math(\\'1 + 3\\')` and then `math(\\'2 + 4\\')`\\n - Minimize the number of `math` actions as much as possible. For instance, instead of calling 2. math(\"what is the 10% of $1\") and then call 3. math(\"$1 + $2\"), you MUST call 2. math(\"what is the 110% of $1\") instead, which will reduce the number of math actions.\\n - You can optionally provide a list of strings as `context` to help the agent solve the problem. If there are multiple contexts you need to answer the question, you can provide them as a list of strings.\\n - `math` action will not see the output of the previous actions unless you provide it as `context`. You MUST provide the output of the previous actions as `context` if you need to do math on it.\\n - You MUST NEVER provide `search` type action\\'s outputs as a variable in the `problem` argument. This is because `search` returns a text blob that contains the information about the entity, not a number or value. Therefore, when you need to provide an output of `search` action, you MUST provide it as a `context` argument to `math` action. For example, 1. search(\"Barack Obama\") and then 2. math(\"age of $1\") is NEVER allowed. Use 2. math(\"age of Barack Obama\", context=[\"$1\"]) instead.\\n - When you ask a question about `context`, specify the units. For instance, \"what is xx in height?\" or \"what is xx in millions?\" instead of \"what is xx?\"' args_schema= func=.calculate_expression at 0x119a318a0> {'problem': 'pow($0, 3)', 'context': ['$0']}\n", + "name='math' description='math(problem: str, context: Optional[List[str]] = None, config: Optional[langchain_core.runnables.config.RunnableConfig] = None) - math(problem: str, context: Optional[list[str]]) -> float:\\n - Solves the provided math problem.\\n - `problem` can be either a simple math problem (e.g. \"1 + 3\") or a word problem (e.g. \"how many apples are there if there are 3 apples and 2 apples\").\\n - You cannot calculate multiple expressions in one call. For instance, `math(\\'1 + 3, 2 + 4\\')` does not work. If you need to calculate multiple expressions, you need to call them separately like `math(\\'1 + 3\\')` and then `math(\\'2 + 4\\')`\\n - Minimize the number of `math` actions as much as possible. For instance, instead of calling 2. math(\"what is the 10% of $1\") and then call 3. math(\"$1 + $2\"), you MUST call 2. math(\"what is the 110% of $1\") instead, which will reduce the number of math actions.\\n - You can optionally provide a list of strings as `context` to help the agent solve the problem. If there are multiple contexts you need to answer the question, you can provide them as a list of strings.\\n - `math` action will not see the output of the previous actions unless you provide it as `context`. You MUST provide the output of the previous actions as `context` if you need to do math on it.\\n - You MUST NEVER provide `search` type action\\'s outputs as a variable in the `problem` argument. This is because `search` returns a text blob that contains the information about the entity, not a number or value. Therefore, when you need to provide an output of `search` action, you MUST provide it as a `context` argument to `math` action. For example, 1. search(\"Barack Obama\") and then 2. math(\"age of $1\") is NEVER allowed. Use 2. math(\"age of Barack Obama\", context=[\"$1\"]) instead.\\n - When you ask a question about `context`, specify the units. For instance, \"what is xx in height?\" or \"what is xx in millions?\" instead of \"what is xx?\"' args_schema= func=.calculate_expression at 0x10f354ea0> {'problem': 'raise $0 to the 3rd power', 'context': ['$0']}\n", "---\n", "join ()\n", "---\n" @@ -280,8 +301,8 @@ "example_question = \"What's the temperature in SF raised to the 3rd power?\"\n", "\n", "for task in planner.stream([HumanMessage(content=example_question)]):\n", - " print(task['tool'], task['args'])\n", - " print('---')" + " print(task[\"tool\"], task[\"args\"])\n", + " print(\"---\")" ] }, { @@ -308,7 +329,7 @@ }, { "cell_type": "code", - "execution_count": 48, + "execution_count": 9, "id": "c1fbafdd-42d4-4575-8466-e5951cee71f4", "metadata": { "jp-MarkdownHeadingCollapsed": true @@ -334,6 +355,7 @@ " results[int(message.additional_kwargs[\"idx\"])] = message.content\n", " return results\n", "\n", + "\n", "class SchedulerInput(TypedDict):\n", " messages: List[BaseMessage]\n", " tasks: Iterable[Task]\n", @@ -348,7 +370,9 @@ " if isinstance(args, str):\n", " resolved_args = _resolve_arg(args, observations)\n", " elif isinstance(args, dict):\n", - " resolved_args = {key: _resolve_arg(val, observations) for key, val in args.items()}\n", + " resolved_args = {\n", + " key: _resolve_arg(val, observations) for key, val in args.items()\n", + " }\n", " else:\n", " # This will likely fail\n", " resolved_args = args\n", @@ -382,30 +406,30 @@ "\n", "@as_runnable\n", "def schedule_task(task_inputs, config):\n", - " task: Task = task_inputs['task']\n", - " observations: Dict[int, Any] = task_inputs['observations']\n", + " task: Task = task_inputs[\"task\"]\n", + " observations: Dict[int, Any] = task_inputs[\"observations\"]\n", " try:\n", " observation = _execute_task(task, observations, config)\n", " except Exception:\n", " import traceback\n", - " observation = traceback.format_exception() #repr(e) + \n", - " observations[task['idx']] = observation\n", "\n", - "def schedule_pending_task(task: Task, observations: Dict[int, Any], retry_after: float = 0.2):\n", + " observation = traceback.format_exception() # repr(e) +\n", + " observations[task[\"idx\"]] = observation\n", + "\n", + "\n", + "def schedule_pending_task(\n", + " task: Task, observations: Dict[int, Any], retry_after: float = 0.2\n", + "):\n", " while True:\n", " deps = task[\"dependencies\"]\n", - " if (\n", - " deps\n", - " and (\n", - " any([dep not in observations for dep in deps])\n", - " )\n", - " ):\n", + " if deps and (any([dep not in observations for dep in deps])):\n", " # Dependencies not yet satisfied\n", " time.sleep(retry_after)\n", " continue\n", " schedule_task.invoke({\"task\": task, \"observations\": observations})\n", " break\n", "\n", + "\n", "@as_runnable\n", "def schedule_tasks(scheduler_input: SchedulerInput) -> List[FunctionMessage]:\n", " \"\"\"Group the tasks into a DAG schedule.\"\"\"\n", @@ -425,19 +449,23 @@ " # ^^ We assume each task inserts a different key above to\n", " # avoid race conditions...\n", " futures = []\n", - " retry_after = 0.25 # Retry every quarter second\n", + " retry_after = 0.25 # Retry every quarter second\n", " with ThreadPoolExecutor() as executor:\n", " for task in tasks:\n", " deps = task[\"dependencies\"]\n", - " task_names[task[\"idx\"]] = task[\"tool\"] if isinstance(task[\"tool\"], str) else task[\"tool\"].name\n", + " task_names[task[\"idx\"]] = (\n", + " task[\"tool\"] if isinstance(task[\"tool\"], str) else task[\"tool\"].name\n", + " )\n", " if (\n", " # Depends on other tasks\n", " deps\n", - " and (\n", - " any([dep not in observations for dep in deps])\n", - " )\n", + " and (any([dep not in observations for dep in deps]))\n", " ):\n", - " futures.append(executor.submit(schedule_pending_task, task, observations, retry_after))\n", + " futures.append(\n", + " executor.submit(\n", + " schedule_pending_task, task, observations, retry_after\n", + " )\n", + " )\n", " else:\n", " # No deps or all deps satisfied\n", " # can schedule now\n", @@ -448,34 +476,39 @@ " # Wait for them to complete\n", " wait(futures)\n", " # Convert observations to new tool messages to add to the state\n", - " new_observations = {k: (task_names[k], observations[k]) for k in sorted(observations.keys() - originals)}\n", + " new_observations = {\n", + " k: (task_names[k], observations[k])\n", + " for k in sorted(observations.keys() - originals)\n", + " }\n", " tool_messages = [\n", - " FunctionMessage(\n", - " name=name,\n", - " content=str(obs),\n", - " additional_kwargs={\"idx\": k}\n", - " ) for k, (name, obs) in new_observations.items()]\n", + " FunctionMessage(name=name, content=str(obs), additional_kwargs={\"idx\": k})\n", + " for k, (name, obs) in new_observations.items()\n", + " ]\n", " return tool_messages" ] }, { "cell_type": "code", - "execution_count": 49, + "execution_count": 10, "id": "052f6b16-103a-40e9-94dd-8fcc37e77ba4", "metadata": {}, "outputs": [], "source": [ "import itertools\n", "\n", + "\n", "@as_runnable\n", "def plan_and_schedule(messages: List[BaseMessage], config):\n", " tasks = planner.stream(messages, config)\n", " # Begin executing the planner immediately\n", " tasks = itertools.chain([next(tasks)], tasks)\n", - " scheduled_tasks = schedule_tasks.invoke({\n", - " \"messages\": messages,\n", - " \"tasks\": tasks,\n", - " }, config)\n", + " scheduled_tasks = schedule_tasks.invoke(\n", + " {\n", + " \"messages\": messages,\n", + " \"tasks\": tasks,\n", + " },\n", + " config,\n", + " )\n", " return scheduled_tasks" ] }, @@ -491,7 +524,7 @@ }, { "cell_type": "code", - "execution_count": 50, + "execution_count": 11, "id": "55142257-2674-4a47-988e-0d2810917329", "metadata": {}, "outputs": [], @@ -501,19 +534,19 @@ }, { "cell_type": "code", - "execution_count": 51, + "execution_count": 12, "id": "a98e0525-2fcf-4fa1-baf6-79858bb8a6bd", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "[FunctionMessage(content=\"[{'url': 'https://en.climate-data.org/north-america/united-states-of-america/california/san-francisco-385/t/september-9/', 'content': 'San Francisco Weather in September San Francisco weather in September San Francisco weather by month // weather averages 9.6 (49.2) 6.2 (43.2) 14 (57.3) Data: 1999 - 2019: avg. Sun hours San Francisco weather and climate for further months San Francisco weather in September // weather averages Airport close to San FranciscoJanuary February March April May June July August September October November December; Avg. Temperature °C (°F) 9.6 °C (49.2) °F. 10.5 °C (50.8) °F. 11.6 °C'}]\", additional_kwargs={'idx': 1}, name='tavily_search_results_json'),\n", - " FunctionMessage(content='1', additional_kwargs={'idx': 2}, name='math'),\n", - " FunctionMessage(content='join', additional_kwargs={'idx': 3}, name='join')]" + "[FunctionMessage(content='[]', additional_kwargs={'idx': 0}, name='tavily_search_results_json'),\n", + " FunctionMessage(content='ValueError(\\'Failed to evaluate \"N/A\". Raised error: KeyError(\\\\\\'A\\\\\\'). Please try again with a valid numerical expression\\')', additional_kwargs={'idx': 1}, name='math'),\n", + " FunctionMessage(content='join', additional_kwargs={'idx': 2}, name='join')]" ] }, - "execution_count": 51, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -539,7 +572,7 @@ }, { "cell_type": "code", - "execution_count": 52, + "execution_count": 13, "id": "942dab42-ad42-4ba2-90d5-49edbe4fae68", "metadata": {}, "outputs": [], @@ -548,20 +581,31 @@ "from langchain.chains.openai_functions import create_structured_output_runnable\n", "from langchain_core.messages import AIMessage\n", "\n", + "\n", "class FinalResponse(BaseModel):\n", " \"\"\"The final response/answer.\"\"\"\n", + "\n", " response: str\n", "\n", + "\n", "class Replan(BaseModel):\n", - " feedback: str = Field(description=\"Analysis of the previous attempts and recommendations on what needs to be fixed.\")\n", + " feedback: str = Field(\n", + " description=\"Analysis of the previous attempts and recommendations on what needs to be fixed.\"\n", + " )\n", + "\n", "\n", "class JoinOutputs(BaseModel):\n", " \"\"\"Decide whether to replan or whether you can return the final response.\"\"\"\n", - " thought: str = Field(description=\"The chain of thought reasoning for the selected action\")\n", + "\n", + " thought: str = Field(\n", + " description=\"The chain of thought reasoning for the selected action\"\n", + " )\n", " action: Union[FinalResponse, Replan]\n", "\n", "\n", - "joiner_prompt = hub.pull(\"wfh/llm-compiler-joiner\").partial(examples=\"\") # You can optionally add examples\n", + "joiner_prompt = hub.pull(\"wfh/llm-compiler-joiner\").partial(\n", + " examples=\"\"\n", + ") # You can optionally add examples\n", "llm = ChatOpenAI(model=\"gpt-4-turbo-preview\")\n", "\n", "runnable = create_structured_output_runnable(JoinOutputs, llm, joiner_prompt)" @@ -578,7 +622,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "id": "951a33cf-2a05-4a33-899a-0ab1d97122fa", "metadata": {}, "outputs": [], @@ -586,7 +630,11 @@ "def _parse_joiner_output(decision: JoinOutputs) -> List[BaseMessage]:\n", " response = [AIMessage(content=f\"Thought: {decision.thought}\")]\n", " if isinstance(decision.action, Replan):\n", - " return response + [SystemMessage(content=f\"Context from last attempt: {decision.action.feedback}\")]\n", + " return response + [\n", + " SystemMessage(\n", + " content=f\"Context from last attempt: {decision.action.feedback}\"\n", + " )\n", + " ]\n", " else:\n", " return response + [AIMessage(content=decision.action.response)]\n", "\n", @@ -599,16 +647,13 @@ " break\n", " return {\"messages\": selected[::-1]}\n", "\n", - "joiner = (\n", - " select_recent_messages\n", - " | runnable\n", - " | _parse_joiner_output\n", - ")" + "\n", + "joiner = select_recent_messages | runnable | _parse_joiner_output" ] }, { "cell_type": "code", - "execution_count": 53, + "execution_count": 15, "id": "1e49d4b1-8266-4520-a566-1448b1c31c8f", "metadata": {}, "outputs": [], @@ -618,18 +663,18 @@ }, { "cell_type": "code", - "execution_count": 54, + "execution_count": 16, "id": "31854dfd-b82f-4c24-9b58-6bae66777909", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "[AIMessage(content=\"Thought: The information provided gives an average temperature for San Francisco in different months, but it doesn't specify the current temperature or any specific temperature to be raised to the 3rd power. Without the current temperature or a specific temperature value, it's impossible to calculate its value raised to the 3rd power.\"),\n", - " SystemMessage(content='Context from last attempt: The information provided is not sufficient to answer the question as it lacks the current temperature of San Francisco or any specific temperature value to be raised to the 3rd power. Need to find the current or a specific temperature to perform the calculation.')]" + "[AIMessage(content='Thought: The search did not return any results, and the attempt to calculate the temperature in San Francisco raised to the 3rd power failed due to missing temperature information.'),\n", + " SystemMessage(content='Context from last attempt: I need to find the current temperature in San Francisco before calculating its value raised to the 3rd power.')]" ] }, - "execution_count": 54, + "execution_count": 16, "metadata": {}, "output_type": "execute_result" } @@ -654,7 +699,7 @@ }, { "cell_type": "code", - "execution_count": 55, + "execution_count": 17, "id": "768b5f11-e3d2-47be-8143-a7dcd8765243", "metadata": {}, "outputs": [], @@ -682,6 +727,7 @@ " return END\n", " return \"plan_and_schedule\"\n", "\n", + "\n", "graph_builder.add_conditional_edges(\n", " start_key=\"join\",\n", " # Next, we pass in the function that will determine which node is called next.\n", @@ -703,7 +749,7 @@ }, { "cell_type": "code", - "execution_count": 56, + "execution_count": 18, "id": "5bc4584a-e31c-4065-805e-76a6db30676a", "metadata": {}, "outputs": [ @@ -711,11 +757,15 @@ "name": "stdout", "output_type": "stream", "text": [ - "{'plan_and_schedule': [FunctionMessage(content='[{\\'url\\': \\'https://www.statista.com/statistics/188087/gdp-of-the-us-federal-state-of-new-york-since-1997/\\', \\'content\\': \"Strategy and business building for the data-driven economy: U.S. real GDP of New York 2000-2022 Real gross domestic product of New York in the United States from 2000 to 2022 (in billion U.S. dollars) Economy U.S. New York metro area GDP 2001-2022 You only have access to basic statistics. U.S. state and local government outstanding debt 2021, by state Demographics Resident population in New York 1960-2022In 2022, the real gross domestic product (GDP) of New York was about 1.56 trillion U.S. dollars. This is an increase from the previous year, when the state\\'s GDP stood at 1.51 trillion...\"}]', additional_kwargs={'idx': 0}, name='tavily_search_results_json')]}\n", + "{'plan_and_schedule': [FunctionMessage(content='[{\\'url\\': \\'https://www.governor.ny.gov/programs/fy-2024-new-york-state-budget\\', \\'content\\': \"The $229 billion FY 2024 New York State Budget reflects Governor Hochul\\'s bold agenda to make New York more affordable, FY 2024 Budget Assets FY 2024 New York State Budget Highlights Improving Public Safety GOVERNOR HOME GOVERNOR KATHY HOCHUL FY 2024 New York State Budget Transformative investments to support New York\\'s business community and boost the state economy.The $229 billion FY 2024 NYS Budget reflects Governor Hochul\\'s bold agenda to make New York more affordable, more livable, and safer.\"}]', additional_kwargs={'idx': 0}, name='tavily_search_results_json')]}\n", "---\n", - "{'join': [AIMessage(content='Thought: The search result provides the information that in 2022, the real gross domestic product (GDP) of New York was about 1.56 trillion U.S. dollars.'), AIMessage(content='The GDP of New York in 2022 was about 1.56 trillion U.S. dollars.')]}\n", + "{'join': [AIMessage(content=\"Thought: The information provided does not specify the Gross Domestic Product (GDP) of New York, but instead provides details about the state's budget for fiscal year 2024, which is $229 billion. This budget figure cannot be accurately equated to the GDP.\"), SystemMessage(content=\"Context from last attempt: The search results provided information about New York's state budget rather than its GDP. To answer the user's question, we need to find specific data on New York's GDP, not its budget.\")]}\n", "---\n", - "{'__end__': [HumanMessage(content=\"What's the GDP of New York?\"), FunctionMessage(content='[{\\'url\\': \\'https://www.statista.com/statistics/188087/gdp-of-the-us-federal-state-of-new-york-since-1997/\\', \\'content\\': \"Strategy and business building for the data-driven economy: U.S. real GDP of New York 2000-2022 Real gross domestic product of New York in the United States from 2000 to 2022 (in billion U.S. dollars) Economy U.S. New York metro area GDP 2001-2022 You only have access to basic statistics. U.S. state and local government outstanding debt 2021, by state Demographics Resident population in New York 1960-2022In 2022, the real gross domestic product (GDP) of New York was about 1.56 trillion U.S. dollars. This is an increase from the previous year, when the state\\'s GDP stood at 1.51 trillion...\"}]', additional_kwargs={'idx': 0}, name='tavily_search_results_json'), AIMessage(content='Thought: The search result provides the information that in 2022, the real gross domestic product (GDP) of New York was about 1.56 trillion U.S. dollars.'), AIMessage(content='The GDP of New York in 2022 was about 1.56 trillion U.S. dollars.')]}\n", + "{'plan_and_schedule': [FunctionMessage(content=\"[{'url': 'https://en.wikipedia.org/wiki/Economy_of_New_York_(state)', 'content': 'The economy of the State of New York is reflected in its gross state product in 2022 of $2.053 trillion, ranking third Contents Economy of New York (state) New York City-centered metropolitan statistical area produced a gross metropolitan product (GMP) of $US2.0 trillion, of the items in which New York ranks high nationally:The economy of the State of New York is reflected in its gross state product in 2022 of $2.053 trillion, ranking third in size behind the larger states of\\\\xa0...'}]\", additional_kwargs={'idx': 1}, name='tavily_search_results_json')]}\n", + "---\n", + "{'join': [AIMessage(content=\"Thought: The required information about New York's GDP is provided in the search results. In 2022, New York had a Gross State Product (GSP) of $2.053 trillion.\"), AIMessage(content='The Gross Domestic Product (GDP) of New York in 2022 was $2.053 trillion.')]}\n", + "---\n", + "{'__end__': [HumanMessage(content=\"What's the GDP of New York?\"), FunctionMessage(content='[{\\'url\\': \\'https://www.governor.ny.gov/programs/fy-2024-new-york-state-budget\\', \\'content\\': \"The $229 billion FY 2024 New York State Budget reflects Governor Hochul\\'s bold agenda to make New York more affordable, FY 2024 Budget Assets FY 2024 New York State Budget Highlights Improving Public Safety GOVERNOR HOME GOVERNOR KATHY HOCHUL FY 2024 New York State Budget Transformative investments to support New York\\'s business community and boost the state economy.The $229 billion FY 2024 NYS Budget reflects Governor Hochul\\'s bold agenda to make New York more affordable, more livable, and safer.\"}]', additional_kwargs={'idx': 0}, name='tavily_search_results_json'), AIMessage(content=\"Thought: The information provided does not specify the Gross Domestic Product (GDP) of New York, but instead provides details about the state's budget for fiscal year 2024, which is $229 billion. This budget figure cannot be accurately equated to the GDP.\"), SystemMessage(content=\"Context from last attempt: The search results provided information about New York's state budget rather than its GDP. To answer the user's question, we need to find specific data on New York's GDP, not its budget. - Begin counting at : 1\"), FunctionMessage(content=\"[{'url': 'https://en.wikipedia.org/wiki/Economy_of_New_York_(state)', 'content': 'The economy of the State of New York is reflected in its gross state product in 2022 of $2.053 trillion, ranking third Contents Economy of New York (state) New York City-centered metropolitan statistical area produced a gross metropolitan product (GMP) of $US2.0 trillion, of the items in which New York ranks high nationally:The economy of the State of New York is reflected in its gross state product in 2022 of $2.053 trillion, ranking third in size behind the larger states of\\\\xa0...'}]\", additional_kwargs={'idx': 1}, name='tavily_search_results_json'), AIMessage(content=\"Thought: The required information about New York's GDP is provided in the search results. In 2022, New York had a Gross State Product (GSP) of $2.053 trillion.\"), AIMessage(content='The Gross Domestic Product (GDP) of New York in 2022 was $2.053 trillion.')]}\n", "---\n" ] } @@ -723,12 +773,12 @@ "source": [ "for step in chain.stream([HumanMessage(content=\"What's the GDP of New York?\")]):\n", " print(step)\n", - " print('---')\n" + " print(\"---\")" ] }, { "cell_type": "code", - "execution_count": 57, + "execution_count": 19, "id": "b96efd08-5314-44f0-a694-3073b638adad", "metadata": {}, "outputs": [ @@ -736,7 +786,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "The GDP of New York in 2022 was about 1.56 trillion U.S. dollars.\n" + "The Gross Domestic Product (GDP) of New York in 2022 was $2.053 trillion.\n" ] } ], @@ -757,7 +807,7 @@ }, { "cell_type": "code", - "execution_count": 58, + "execution_count": 20, "id": "0b3a0916-d8ca-4092-b91c-d9e2b05259d8", "metadata": {}, "outputs": [ @@ -765,38 +815,38 @@ "name": "stdout", "output_type": "stream", "text": [ - "{'plan_and_schedule': [FunctionMessage(content='[{\\'url\\': \\'https://savetheeaglesinternational.org/old-parrot/\\', \\'content\\': \"What Is The World\\'s Oldest Parrot? Living Long and Healthy Lives: A Look at the World’s Oldest Parrots certain parrot species are considered older: your parrot enters its senior years?One remarkable parrot that defied the odds and lived a long life is Cookie, a cockatoo who reached the impressive age of 83. Cookie spent his entire life at the Brookfield Zoo, serving as a testament to the exceptional care and environment provided by the zookeepers.\"}]', additional_kwargs={'idx': 1}, name='tavily_search_results_json'), FunctionMessage(content=\"[{'url': 'https://www.animalwised.com/how-long-does-a-parrot-live-3974.html', 'content': 'How Long Does a Parrot Live? How long does a parrot live in captivity? How long does a parrot live in the wild? Why do parrots live so long?Below is the average life expectancy of parrots in captivity, based on their species. Lovebirds. Lovebirds are members of the genus Agapornis, a small group of parrots in the parrot family Psittaculidae. The average life expectancy of a lovebird is between 12 and 15 years. Depending on care and circumstances, the bird can live up to 20 years ...'}]\", additional_kwargs={'idx': 2}, name='tavily_search_results_json'), FunctionMessage(content='join', additional_kwargs={'idx': 3}, name='join')]}\n", + "{'plan_and_schedule': [FunctionMessage(content=\"[{'url': 'https://a-z-animals.com/blog/discover-the-worlds-oldest-parrot/', 'content': 'How Old Is the World’s Oldest Parrot? Discover the World’s Oldest Parrot Advertisement of debate, so we’ll detail some other parrots whose lifespans may be longer but are hard to verify their exact age. Comparing Parrots’ Lifespans to Other BirdsSep 8, 2023 — Sep 8, 2023The oldest parrot on record is Cookie, a pink cockatoo that survived to the age of 83 and survived his entire life at the Brookfield Zoo.'}]\", additional_kwargs={'idx': 0}, name='tavily_search_results_json'), FunctionMessage(content=\"HTTPError('502 Server Error: Bad Gateway for url: https://api.tavily.com/search')\", additional_kwargs={'idx': 1}, name='tavily_search_results_json'), FunctionMessage(content='join', additional_kwargs={'idx': 2}, name='join')]}\n", "---\n", - "{'join': [AIMessage(content=\"Thought: The oldest parrot ever recorded is Cookie, a cockatoo, who lived to be 83 years old. However, the average lifespan provided is specifically for lovebirds, which is between 12 and 15 years. This information doesn't accurately reflect the average lifespan of all parrot species, which would be necessary to compare with Cookie's age accurately. Since parrots encompass a wide variety of species with different lifespans, the information on lovebirds' lifespan alone is insufficient for a comprehensive comparison.\"), SystemMessage(content=\"Context from last attempt: We need information on the average lifespan of parrots in general, not just lovebirds, to accurately compare with Cookie's age.\")]}\n", + "{'join': [AIMessage(content='Thought: The oldest parrot on record is Cookie, a pink cockatoo, who lived to be 83 years old. However, there was an error fetching additional search results to compare this age to the average lifespan of parrots.'), SystemMessage(content='Context from last attempt: I found the age of the oldest parrot, Cookie, who lived to be 83 years old. However, I need to search again to find the average lifespan of parrots to complete the comparison.')]}\n", "---\n", - "{'plan_and_schedule': [FunctionMessage(content='[{\\'url\\': \\'https://www.petmd.com/bird/how-long-do-parrots-live\\', \\'content\\': \"Average Parrot Lifespan and Aging How Long Do Parrots Live? How to Improve Your Parrot\\'s Lifespan Mcleod DVM, Lianne. The Spruce Pets. How Long do Pet Parrots and Other Birds Live?. 2023.Some pets, such as tortoises and parrots, may live for over 50 years. Because they are a lifelong commitment, lawyers often urge pet parents to provide documented plans for their pet parrots in their wills. Average Parrot Lifespan and Aging. Parrots are an incredibly diverse group of birds known by their scientific name: psittacines.\"}]', additional_kwargs={'idx': 4}, name='tavily_search_results_json')]}\n", + "{'plan_and_schedule': [FunctionMessage(content='[{\\'url\\': \\'https://www.turlockvet.com/site/blog/2023/07/15/parrot-lifespan--how-long-pet-parrots-live\\', \\'content\\': \"Parrot Lifespan the lifespan of a parrot?\\'. Parrot Lifespan: How Long Do Pet Parrots Live? how long they actually live and what you should know about owning a parrot.Jul 15, 2023 — Jul 15, 2023Generally, the average lifespan of smaller species of parrots such as Budgies and Cockatiels is about 5 - 15 years, while larger parrots such as\\\\xa0...\"}]', additional_kwargs={'idx': 3}, name='tavily_search_results_json')]}\n", "---\n", - "{'join': [AIMessage(content=\"Thought: The information provided does not give a specific average lifespan for parrots in general, which is necessary for accurately comparing Cookie's age to the average lifespan of parrots. The search result mentions that parrots can live over 50 years but does not provide a detailed average lifespan applicable to all or most parrot species.\"), SystemMessage(content=\"Context from last attempt: We need information on the average lifespan of parrots in general to accurately compare with Cookie's age of 83 years. The provided information doesn't specify an average lifespan for parrots as a whole.\")]}\n", + "{'join': [AIMessage(content=\"Thought: I have found that the oldest parrot on record, Cookie, lived to be 83 years old. Additionally, I've found that the average lifespan of parrots varies by species, with smaller species like Budgies and Cockatiels living between 5-15 years, and larger parrots potentially living longer. This allows me to compare Cookie's age to the average lifespan of smaller parrot species.\"), AIMessage(content=\"The oldest parrot on record is Cookie, a pink cockatoo, who lived to be 83 years old. Compared to the average lifespan of smaller parrot species such as Budgies and Cockatiels, which is about 5-15 years, Cookie lived significantly longer. The average lifespan of larger parrot species wasn't specified, but it's implied that larger parrots may live longer than smaller species, yet likely still much less than 83 years.\")]}\n", "---\n", - "{'plan_and_schedule': [FunctionMessage(content='join', additional_kwargs={'idx': 5}, name='join')]}\n", - "---\n", - "{'join': [AIMessage(content=\"Thought: Despite multiple attempts, the specific average lifespan of parrots as a whole has not been provided. The information obtained mentions that parrots can live over 50 years, but a more precise average is necessary for a detailed comparison with Cookie's age of 83 years. However, it's clear that Cookie lived significantly longer than the average lifespan of many parrot species, including lovebirds which have an average lifespan of 12 to 15 years.\"), AIMessage(content=\"The oldest parrot on record is Cookie, a cockatoo, who lived to be 83 years old. While specific average lifespan information for all parrot species has not been provided, it's mentioned that some parrots can live over 50 years. This suggests that Cookie lived significantly longer than the average lifespan for many parrot species. For instance, lovebirds, a type of parrot, have an average lifespan of 12 to 15 years, indicating that Cookie's lifespan was exceptional among parrots.\")]}\n", - "---\n", - "{'__end__': [HumanMessage(content=\"What's the oldest parrot alive, and how much longer is that than the average?\"), FunctionMessage(content='[{\\'url\\': \\'https://savetheeaglesinternational.org/old-parrot/\\', \\'content\\': \"What Is The World\\'s Oldest Parrot? Living Long and Healthy Lives: A Look at the World’s Oldest Parrots certain parrot species are considered older: your parrot enters its senior years?One remarkable parrot that defied the odds and lived a long life is Cookie, a cockatoo who reached the impressive age of 83. Cookie spent his entire life at the Brookfield Zoo, serving as a testament to the exceptional care and environment provided by the zookeepers.\"}]', additional_kwargs={'idx': 1}, name='tavily_search_results_json'), FunctionMessage(content=\"[{'url': 'https://www.animalwised.com/how-long-does-a-parrot-live-3974.html', 'content': 'How Long Does a Parrot Live? How long does a parrot live in captivity? How long does a parrot live in the wild? Why do parrots live so long?Below is the average life expectancy of parrots in captivity, based on their species. Lovebirds. Lovebirds are members of the genus Agapornis, a small group of parrots in the parrot family Psittaculidae. The average life expectancy of a lovebird is between 12 and 15 years. Depending on care and circumstances, the bird can live up to 20 years ...'}]\", additional_kwargs={'idx': 2}, name='tavily_search_results_json'), FunctionMessage(content='join', additional_kwargs={'idx': 3}, name='join'), AIMessage(content=\"Thought: The oldest parrot ever recorded is Cookie, a cockatoo, who lived to be 83 years old. However, the average lifespan provided is specifically for lovebirds, which is between 12 and 15 years. This information doesn't accurately reflect the average lifespan of all parrot species, which would be necessary to compare with Cookie's age accurately. Since parrots encompass a wide variety of species with different lifespans, the information on lovebirds' lifespan alone is insufficient for a comprehensive comparison.\"), SystemMessage(content=\"Context from last attempt: We need information on the average lifespan of parrots in general, not just lovebirds, to accurately compare with Cookie's age. - Begin counting at : 4\"), FunctionMessage(content='[{\\'url\\': \\'https://www.petmd.com/bird/how-long-do-parrots-live\\', \\'content\\': \"Average Parrot Lifespan and Aging How Long Do Parrots Live? How to Improve Your Parrot\\'s Lifespan Mcleod DVM, Lianne. The Spruce Pets. How Long do Pet Parrots and Other Birds Live?. 2023.Some pets, such as tortoises and parrots, may live for over 50 years. Because they are a lifelong commitment, lawyers often urge pet parents to provide documented plans for their pet parrots in their wills. Average Parrot Lifespan and Aging. Parrots are an incredibly diverse group of birds known by their scientific name: psittacines.\"}]', additional_kwargs={'idx': 4}, name='tavily_search_results_json'), AIMessage(content=\"Thought: The information provided does not give a specific average lifespan for parrots in general, which is necessary for accurately comparing Cookie's age to the average lifespan of parrots. The search result mentions that parrots can live over 50 years but does not provide a detailed average lifespan applicable to all or most parrot species.\"), SystemMessage(content=\"Context from last attempt: We need information on the average lifespan of parrots in general to accurately compare with Cookie's age of 83 years. The provided information doesn't specify an average lifespan for parrots as a whole. - Begin counting at : 5\"), FunctionMessage(content='join', additional_kwargs={'idx': 5}, name='join'), AIMessage(content=\"Thought: Despite multiple attempts, the specific average lifespan of parrots as a whole has not been provided. The information obtained mentions that parrots can live over 50 years, but a more precise average is necessary for a detailed comparison with Cookie's age of 83 years. However, it's clear that Cookie lived significantly longer than the average lifespan of many parrot species, including lovebirds which have an average lifespan of 12 to 15 years.\"), AIMessage(content=\"The oldest parrot on record is Cookie, a cockatoo, who lived to be 83 years old. While specific average lifespan information for all parrot species has not been provided, it's mentioned that some parrots can live over 50 years. This suggests that Cookie lived significantly longer than the average lifespan for many parrot species. For instance, lovebirds, a type of parrot, have an average lifespan of 12 to 15 years, indicating that Cookie's lifespan was exceptional among parrots.\")]}\n", + "{'__end__': [HumanMessage(content=\"What's the oldest parrot alive, and how much longer is that than the average?\"), FunctionMessage(content=\"[{'url': 'https://a-z-animals.com/blog/discover-the-worlds-oldest-parrot/', 'content': 'How Old Is the World’s Oldest Parrot? Discover the World’s Oldest Parrot Advertisement of debate, so we’ll detail some other parrots whose lifespans may be longer but are hard to verify their exact age. Comparing Parrots’ Lifespans to Other BirdsSep 8, 2023 — Sep 8, 2023The oldest parrot on record is Cookie, a pink cockatoo that survived to the age of 83 and survived his entire life at the Brookfield Zoo.'}]\", additional_kwargs={'idx': 0}, name='tavily_search_results_json'), FunctionMessage(content=\"HTTPError('502 Server Error: Bad Gateway for url: https://api.tavily.com/search')\", additional_kwargs={'idx': 1}, name='tavily_search_results_json'), FunctionMessage(content='join', additional_kwargs={'idx': 2}, name='join'), AIMessage(content='Thought: The oldest parrot on record is Cookie, a pink cockatoo, who lived to be 83 years old. However, there was an error fetching additional search results to compare this age to the average lifespan of parrots.'), SystemMessage(content='Context from last attempt: I found the age of the oldest parrot, Cookie, who lived to be 83 years old. However, I need to search again to find the average lifespan of parrots to complete the comparison. - Begin counting at : 3'), FunctionMessage(content='[{\\'url\\': \\'https://www.turlockvet.com/site/blog/2023/07/15/parrot-lifespan--how-long-pet-parrots-live\\', \\'content\\': \"Parrot Lifespan the lifespan of a parrot?\\'. Parrot Lifespan: How Long Do Pet Parrots Live? how long they actually live and what you should know about owning a parrot.Jul 15, 2023 — Jul 15, 2023Generally, the average lifespan of smaller species of parrots such as Budgies and Cockatiels is about 5 - 15 years, while larger parrots such as\\\\xa0...\"}]', additional_kwargs={'idx': 3}, name='tavily_search_results_json'), AIMessage(content=\"Thought: I have found that the oldest parrot on record, Cookie, lived to be 83 years old. Additionally, I've found that the average lifespan of parrots varies by species, with smaller species like Budgies and Cockatiels living between 5-15 years, and larger parrots potentially living longer. This allows me to compare Cookie's age to the average lifespan of smaller parrot species.\"), AIMessage(content=\"The oldest parrot on record is Cookie, a pink cockatoo, who lived to be 83 years old. Compared to the average lifespan of smaller parrot species such as Budgies and Cockatiels, which is about 5-15 years, Cookie lived significantly longer. The average lifespan of larger parrot species wasn't specified, but it's implied that larger parrots may live longer than smaller species, yet likely still much less than 83 years.\")]}\n", "---\n" ] } ], "source": [ "steps = chain.stream(\n", - " [HumanMessage(content=\"What's the oldest parrot alive, and how much longer is that than the average?\")],\n", + " [\n", + " HumanMessage(\n", + " content=\"What's the oldest parrot alive, and how much longer is that than the average?\"\n", + " )\n", + " ],\n", " {\n", " \"recursion_limit\": 100,\n", " },\n", ")\n", "for step in steps:\n", " print(step)\n", - " print('---')" + " print(\"---\")" ] }, { "cell_type": "code", - "execution_count": 59, + "execution_count": 21, "id": "6c65c414-7668-4fdf-ba97-f42f659b1317", "metadata": {}, "outputs": [ @@ -804,7 +854,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "The oldest parrot on record is Cookie, a cockatoo, who lived to be 83 years old. While specific average lifespan information for all parrot species has not been provided, it's mentioned that some parrots can live over 50 years. This suggests that Cookie lived significantly longer than the average lifespan for many parrot species. For instance, lovebirds, a type of parrot, have an average lifespan of 12 to 15 years, indicating that Cookie's lifespan was exceptional among parrots.\n" + "The oldest parrot on record is Cookie, a pink cockatoo, who lived to be 83 years old. Compared to the average lifespan of smaller parrot species such as Budgies and Cockatiels, which is about 5-15 years, Cookie lived significantly longer. The average lifespan of larger parrot species wasn't specified, but it's implied that larger parrots may live longer than smaller species, yet likely still much less than 83 years.\n" ] } ], @@ -823,7 +873,7 @@ }, { "cell_type": "code", - "execution_count": 60, + "execution_count": 22, "id": "38d3ea91-59ba-4267-8060-ed75bbc840c6", "metadata": {}, "outputs": [ @@ -831,20 +881,26 @@ "name": "stdout", "output_type": "stream", "text": [ - "{'plan_and_schedule': [FunctionMessage(content='3307.0', additional_kwargs={'idx': 0}, name='math'), FunctionMessage(content='7.565011820330969', additional_kwargs={'idx': 1}, name='math'), FunctionMessage(content='join', additional_kwargs={'idx': 2}, name='join')]}\n", - "{'join': [AIMessage(content='Thought: The first calculation resulted in 3307.0, and the second calculation gave 7.565011820330969. To find the sum of these two values, I will simply add them together.'), AIMessage(content='The sum of ((3*(4+5)/0.5)+3245) + 8 and 32/4.23 is approximately 3314.565.')]}\n", - "{'__end__': [HumanMessage(content=\"What's ((3*(4+5)/0.5)+3245) + 8? What's 32/4.23? What's the sum of those two values?\"), FunctionMessage(content='3307.0', additional_kwargs={'idx': 0}, name='math'), FunctionMessage(content='7.565011820330969', additional_kwargs={'idx': 1}, name='math'), FunctionMessage(content='join', additional_kwargs={'idx': 2}, name='join'), AIMessage(content='Thought: The first calculation resulted in 3307.0, and the second calculation gave 7.565011820330969. To find the sum of these two values, I will simply add them together.'), AIMessage(content='The sum of ((3*(4+5)/0.5)+3245) + 8 and 32/4.23 is approximately 3314.565.')]}\n" + "{'plan_and_schedule': [FunctionMessage(content='3307.0', additional_kwargs={'idx': 1}, name='math'), FunctionMessage(content='7.565011820330969', additional_kwargs={'idx': 2}, name='math'), FunctionMessage(content='3314.565011820331', additional_kwargs={'idx': 3}, name='math'), FunctionMessage(content='join', additional_kwargs={'idx': 4}, name='join')]}\n", + "{'join': [AIMessage(content=\"Thought: The calculations for each part of the user's question have been successfully completed. The first calculation resulted in 3307.0, the second in 7.565011820330969, and the sum of those two values was correctly found to be 3314.565011820331.\"), AIMessage(content='The result of ((3*(4+5)/0.5)+3245) + 8 is 3307.0, the result of 32/4.23 is approximately 7.565, and the sum of those two values is approximately 3314.565.')]}\n", + "{'__end__': [HumanMessage(content=\"What's ((3*(4+5)/0.5)+3245) + 8? What's 32/4.23? What's the sum of those two values?\"), FunctionMessage(content='3307.0', additional_kwargs={'idx': 1}, name='math'), FunctionMessage(content='7.565011820330969', additional_kwargs={'idx': 2}, name='math'), FunctionMessage(content='3314.565011820331', additional_kwargs={'idx': 3}, name='math'), FunctionMessage(content='join', additional_kwargs={'idx': 4}, name='join'), AIMessage(content=\"Thought: The calculations for each part of the user's question have been successfully completed. The first calculation resulted in 3307.0, the second in 7.565011820330969, and the sum of those two values was correctly found to be 3314.565011820331.\"), AIMessage(content='The result of ((3*(4+5)/0.5)+3245) + 8 is 3307.0, the result of 32/4.23 is approximately 7.565, and the sum of those two values is approximately 3314.565.')]}\n" ] } ], "source": [ - "for step in chain.stream([HumanMessage(content=\"What's ((3*(4+5)/0.5)+3245) + 8? What's 32/4.23? What's the sum of those two values?\")]):\n", + "for step in chain.stream(\n", + " [\n", + " HumanMessage(\n", + " content=\"What's ((3*(4+5)/0.5)+3245) + 8? What's 32/4.23? What's the sum of those two values?\"\n", + " )\n", + " ]\n", + "):\n", " print(step)" ] }, { "cell_type": "code", - "execution_count": 61, + "execution_count": 23, "id": "a6cf5fe0-f178-4197-950f-257711bff8d2", "metadata": { "scrolled": true @@ -854,7 +910,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "The sum of ((3*(4+5)/0.5)+3245) + 8 and 32/4.23 is approximately 3314.565.\n" + "The result of ((3*(4+5)/0.5)+3245) + 8 is 3307.0, the result of 32/4.23 is approximately 7.565, and the sum of those two values is approximately 3314.565.\n" ] } ], @@ -862,6 +918,14 @@ "# Final answer\n", "print(step[END][-1].content)" ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "431217e6-4c00-409f-a2bd-40ebff902489", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/examples/plan-and-execute/plan-and-execute.ipynb b/examples/plan-and-execute/plan-and-execute.ipynb index 05fe873de..5bf855522 100644 --- a/examples/plan-and-execute/plan-and-execute.ipynb +++ b/examples/plan-and-execute/plan-and-execute.ipynb @@ -102,6 +102,7 @@ "outputs": [], "source": [ "import os\n", + "\n", "os.environ[\"LANGCHAIN_PROJECT\"] = \"brex\"" ] }, @@ -148,6 +149,7 @@ "from langchain import hub\n", "from langchain.agents import create_openai_functions_agent\n", "from langchain_openai import ChatOpenAI\n", + "\n", "# Get the prompt to use - you can modify this!\n", "prompt = hub.pull(\"hwchase17/openai-functions-agent\")\n", "# Choose the LLM that will drive the agent\n", @@ -198,7 +200,9 @@ } ], "source": [ - "agent_executor.invoke({\"input\": \"who is the winnner of the us open\", \"chat_history\": []})" + "agent_executor.invoke(\n", + " {\"input\": \"who is the winnner of the us open\", \"chat_history\": []}\n", + ")" ] }, { @@ -230,8 +234,7 @@ "\n", "\n", "class PlanExecute(TypedDict):\n", - "\n", - " input: str \n", + " input: str\n", " plan: List[str]\n", " past_steps: Annotated[List[Tuple], operator.add]\n", " response: str" @@ -259,7 +262,10 @@ "\n", "class Plan(BaseModel):\n", " \"\"\"Plan to follow in future\"\"\"\n", - " steps: List[str] = Field(description=\"different steps to follow, should be in sorted order\")\n" + "\n", + " steps: List[str] = Field(\n", + " description=\"different steps to follow, should be in sorted order\"\n", + " )" ] }, { @@ -272,12 +278,16 @@ "from langchain.chains.openai_functions import create_structured_output_runnable\n", "from langchain_core.prompts import ChatPromptTemplate\n", "\n", - "planner_prompt = ChatPromptTemplate.from_template(\"\"\"For the given objective, come up with a simple step by step plan. \\\n", + "planner_prompt = ChatPromptTemplate.from_template(\n", + " \"\"\"For the given objective, come up with a simple step by step plan. \\\n", "This plan should involve individual tasks, that if executed correctly will yield the correct answer. Do not add any superfluous steps. \\\n", "The result of the final step should be the final answer. Make sure that each step has all the information needed - do not skip steps.\n", "\n", - "{objective}\"\"\")\n", - "planner = create_structured_output_runnable(Plan, ChatOpenAI(model=\"gpt-4-turbo-preview\", temperature=0), planner_prompt)" + "{objective}\"\"\"\n", + ")\n", + "planner = create_structured_output_runnable(\n", + " Plan, ChatOpenAI(model=\"gpt-4-turbo-preview\", temperature=0), planner_prompt\n", + ")" ] }, { @@ -298,7 +308,9 @@ } ], "source": [ - "planner.invoke({'objective': 'what is the hometown of the current Australia open winner?'})" + "planner.invoke(\n", + " {\"objective\": \"what is the hometown of the current Australia open winner?\"}\n", + ")" ] }, { @@ -319,11 +331,16 @@ "outputs": [], "source": [ "from langchain.chains.openai_functions import create_openai_fn_runnable\n", + "\n", + "\n", "class Response(BaseModel):\n", " \"\"\"Response to user.\"\"\"\n", + "\n", " response: str\n", "\n", - "replanner_prompt = ChatPromptTemplate.from_template(\"\"\"For the given objective, come up with a simple step by step plan. \\\n", + "\n", + "replanner_prompt = ChatPromptTemplate.from_template(\n", + " \"\"\"For the given objective, come up with a simple step by step plan. \\\n", "This plan should involve individual tasks, that if executed correctly will yield the correct answer. Do not add any superfluous steps. \\\n", "The result of the final step should be the final answer. Make sure that each step has all the information needed - do not skip steps.\n", "\n", @@ -336,10 +353,15 @@ "You have currently done the follow steps:\n", "{past_steps}\n", "\n", - "Update your plan accordingly. If no more steps are needed and you can return to the user, then respond with that. Otherwise, fill out the plan. Only add steps to the plan that still NEED to be done. Do not return previously done steps as part of the plan.\"\"\")\n", + "Update your plan accordingly. If no more steps are needed and you can return to the user, then respond with that. Otherwise, fill out the plan. Only add steps to the plan that still NEED to be done. Do not return previously done steps as part of the plan.\"\"\"\n", + ")\n", "\n", "\n", - "replanner = create_openai_fn_runnable([Plan, Response], ChatOpenAI(model=\"gpt-4-turbo-preview\", temperature=0), replanner_prompt)\n" + "replanner = create_openai_fn_runnable(\n", + " [Plan, Response],\n", + " ChatOpenAI(model=\"gpt-4-turbo-preview\", temperature=0),\n", + " replanner_prompt,\n", + ")" ] }, { @@ -360,14 +382,18 @@ "outputs": [], "source": [ "async def execute_step(state: PlanExecute):\n", - " task = state['plan'][0]\n", + " task = state[\"plan\"][0]\n", " agent_response = await agent_executor.ainvoke({\"input\": task, \"chat_history\": []})\n", - " return {\"past_steps\": (task, agent_response['agent_outcome'].return_values['output'])}\n", + " return {\n", + " \"past_steps\": (task, agent_response[\"agent_outcome\"].return_values[\"output\"])\n", + " }\n", + "\n", "\n", "async def plan_step(state: PlanExecute):\n", " plan = await planner.ainvoke({\"objective\": state[\"input\"]})\n", " return {\"plan\": plan.steps}\n", "\n", + "\n", "async def replan_step(state: PlanExecute):\n", " output = await replanner.ainvoke(state)\n", " if isinstance(output, Response):\n", @@ -375,8 +401,9 @@ " else:\n", " return {\"plan\": output.steps}\n", "\n", + "\n", "def should_end(state: PlanExecute):\n", - " if state['response']:\n", + " if state[\"response\"]:\n", " return True\n", " else:\n", " return False" @@ -405,7 +432,7 @@ "workflow.set_entry_point(\"planner\")\n", "\n", "# From plan we go to agent\n", - "workflow.add_edge('planner', 'agent')\n", + "workflow.add_edge(\"planner\", \"agent\")\n", "\n", "# From agent, we replan\n", "workflow.add_edge(\"agent\", \"replan\")\n", @@ -418,7 +445,7 @@ " # If `tools`, then we call the tool node.\n", " True: END,\n", " False: \"agent\",\n", - " }\n", + " },\n", ")\n", "\n", "# Finally, we compile it!\n", @@ -449,6 +476,7 @@ ], "source": [ "from langchain_core.messages import HumanMessage\n", + "\n", "config = {\"recursion_limit\": 50}\n", "inputs = {\"input\": \"what is the hometown of the 2024 Australia open winner?\"}\n", "async for event in app.astream(inputs, config=config):\n", diff --git a/examples/rewoo/rewoo.ipynb b/examples/rewoo/rewoo.ipynb index 5e90bb7fd..218713d2e 100644 --- a/examples/rewoo/rewoo.ipynb +++ b/examples/rewoo/rewoo.ipynb @@ -13,6 +13,8 @@ "2. Simplify the fine-tuning process. Since the planning data doesn't depend on the outputs of the tool, models can be fine-tuned without actually invoking the tools (in theory).\n", "\n", "\n", + "The following diagram outlines ReWOO's overall computation graph:\n", + "\n", "![ReWoo Diagram](./img/rewoo.png)\n", "\n", "ReWOO is made of 3 modules:\n", @@ -30,7 +32,7 @@ "\n", "The modules with a 🧠 emoji depend on an LLM call. Notice that we avoid redundant calls to the planner LLM by using variable substitution.\n", "\n", - "In this example, each module is represented by a LangGraph node. Let's get started!\n", + "In this example, each module is represented by a LangGraph node. The end result will leave a trace that looks [like this one](https://smith.langchain.com/public/39dbdcf8-fbcc-4479-8e28-15377ca5e653/r). Let's get started!\n", "\n", "## 0. Prerequisites\n", "\n",