From 827d75bc4b1399fc268928bb24f65fa0a7bcd8e4 Mon Sep 17 00:00:00 2001 From: Harrison Chase Date: Wed, 17 May 2023 00:03:22 -0700 Subject: [PATCH 1/5] better handling for parsing errors --- langchain/agents/agent.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/langchain/agents/agent.py b/langchain/agents/agent.py index f73b5f2607a33..2bb96ce7986ff 100644 --- a/langchain/agents/agent.py +++ b/langchain/agents/agent.py @@ -7,7 +7,7 @@ import time from abc import abstractmethod from pathlib import Path -from typing import Any, Dict, List, Optional, Sequence, Tuple, Union +from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union import yaml from pydantic import BaseModel, root_validator @@ -625,7 +625,7 @@ class AgentExecutor(Chain): max_iterations: Optional[int] = 15 max_execution_time: Optional[float] = None early_stopping_method: str = "force" - handle_parsing_errors: bool = False + handle_parsing_errors: Union[bool, str, Callable] = False @classmethod def from_agent_and_tools( @@ -762,14 +762,25 @@ def _take_next_step( **inputs, ) except Exception as e: - if not self.handle_parsing_errors: + if isinstance(self.handle_parsing_errors, bool): + raise_error = not self.handle_parsing_errors + else: + raise_error = False + if raise_error: raise e - text = str(e).split("`")[1] - observation = "Invalid or incomplete response" + text = str(e) + if isinstance(self.handle_parsing_errors, bool): + observation = "Invalid or incomplete response" + elif isinstance(self.handle_parsing_errors, str): + observation = self.handle_parsing_errors + elif callable(self.handle_parsing_errors): + observation = self.handle_parsing_errors(text) + else: + raise ValueError("Got unexpected type of `handle_parsing_errors`") output = AgentAction("_Exception", observation, text) tool_run_kwargs = self.agent.tool_run_logging_kwargs() observation = ExceptionTool().run( - output.tool, + output.tool_input, verbose=self.verbose, color=None, callbacks=run_manager.get_child() if run_manager else None, From e0eeb51dcfeb3d303e0649666f176ebeef366cd1 Mon Sep 17 00:00:00 2001 From: Harrison Chase Date: Wed, 17 May 2023 00:09:31 -0700 Subject: [PATCH 2/5] cr --- .../examples/handle_parsing_errors.ipynb | 346 ++++++++++++++++++ langchain/agents/agent.py | 2 +- 2 files changed, 347 insertions(+), 1 deletion(-) create mode 100644 docs/modules/agents/agent_executors/examples/handle_parsing_errors.ipynb diff --git a/docs/modules/agents/agent_executors/examples/handle_parsing_errors.ipynb b/docs/modules/agents/agent_executors/examples/handle_parsing_errors.ipynb new file mode 100644 index 0000000000000..f7fdfec7337ee --- /dev/null +++ b/docs/modules/agents/agent_executors/examples/handle_parsing_errors.ipynb @@ -0,0 +1,346 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "6317727b", + "metadata": {}, + "source": [ + "# Handle Parsing Errors\n", + "\n", + "Occasionally the LLM cannot determine what step to take because it outputs format in incorrect form to be handled by the output parser. In this case, by default the agent errors. But you can easily control this functionality with `handle_parsing_errors`! Let's explore how." + ] + }, + { + "cell_type": "markdown", + "id": "39cc1a7b", + "metadata": {}, + "source": [ + "## Setup" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "33c7f220", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain import OpenAI, LLMMathChain, SerpAPIWrapper, SQLDatabase, SQLDatabaseChain\n", + "from langchain.agents import initialize_agent, Tool\n", + "from langchain.agents import AgentType\n", + "from langchain.chat_models import ChatOpenAI\n", + "from langchain.agents.types import AGENT_TO_CLASS" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "3de22959", + "metadata": {}, + "outputs": [], + "source": [ + "search = SerpAPIWrapper()\n", + "tools = [\n", + " Tool(\n", + " name = \"Search\",\n", + " func=search.run,\n", + " description=\"useful for when you need to answer questions about current events. You should ask targeted questions\"\n", + " ),\n", + "]" + ] + }, + { + "cell_type": "markdown", + "id": "9f1fc58a", + "metadata": {}, + "source": [ + "## Error\n", + "\n", + "In this scenario, the agent will error (because it fails to output an Action string)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "32ad08d1", + "metadata": {}, + "outputs": [], + "source": [ + "mrkl = initialize_agent(\n", + " tools, \n", + " ChatOpenAI(temperature=0), \n", + " agent=AgentType.CHAT_ZERO_SHOT_REACT_DESCRIPTION, \n", + " verbose=True,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "facb8895", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n" + ] + }, + { + "ename": "OutputParserException", + "evalue": "Could not parse LLM output: I'm sorry, but I cannot provide an answer without an Action. Please provide a valid Action in order for me to assist you.", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)", + "File \u001b[0;32m~/workplace/langchain/langchain/agents/chat/output_parser.py:21\u001b[0m, in \u001b[0;36mChatOutputParser.parse\u001b[0;34m(self, text)\u001b[0m\n\u001b[1;32m 20\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m---> 21\u001b[0m action \u001b[38;5;241m=\u001b[39m \u001b[43mtext\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msplit\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m```\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m]\u001b[49m\n\u001b[1;32m 22\u001b[0m response \u001b[38;5;241m=\u001b[39m json\u001b[38;5;241m.\u001b[39mloads(action\u001b[38;5;241m.\u001b[39mstrip())\n", + "\u001b[0;31mIndexError\u001b[0m: list index out of range", + "\nDuring handling of the above exception, another exception occurred:\n", + "\u001b[0;31mOutputParserException\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[4], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mmrkl\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mWho is Leo DiCaprio\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43ms girlfriend? No need to add Action\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/workplace/langchain/langchain/chains/base.py:236\u001b[0m, in \u001b[0;36mChain.run\u001b[0;34m(self, callbacks, *args, **kwargs)\u001b[0m\n\u001b[1;32m 234\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(args) \u001b[38;5;241m!=\u001b[39m \u001b[38;5;241m1\u001b[39m:\n\u001b[1;32m 235\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m`run` supports only one positional argument.\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m--> 236\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43margs\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcallbacks\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcallbacks\u001b[49m\u001b[43m)\u001b[49m[\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39moutput_keys[\u001b[38;5;241m0\u001b[39m]]\n\u001b[1;32m 238\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m kwargs \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m args:\n\u001b[1;32m 239\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m(kwargs, callbacks\u001b[38;5;241m=\u001b[39mcallbacks)[\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39moutput_keys[\u001b[38;5;241m0\u001b[39m]]\n", + "File \u001b[0;32m~/workplace/langchain/langchain/chains/base.py:140\u001b[0m, in \u001b[0;36mChain.__call__\u001b[0;34m(self, inputs, return_only_outputs, callbacks)\u001b[0m\n\u001b[1;32m 138\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (\u001b[38;5;167;01mKeyboardInterrupt\u001b[39;00m, \u001b[38;5;167;01mException\u001b[39;00m) \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 139\u001b[0m run_manager\u001b[38;5;241m.\u001b[39mon_chain_error(e)\n\u001b[0;32m--> 140\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m e\n\u001b[1;32m 141\u001b[0m run_manager\u001b[38;5;241m.\u001b[39mon_chain_end(outputs)\n\u001b[1;32m 142\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mprep_outputs(inputs, outputs, return_only_outputs)\n", + "File \u001b[0;32m~/workplace/langchain/langchain/chains/base.py:134\u001b[0m, in \u001b[0;36mChain.__call__\u001b[0;34m(self, inputs, return_only_outputs, callbacks)\u001b[0m\n\u001b[1;32m 128\u001b[0m run_manager \u001b[38;5;241m=\u001b[39m callback_manager\u001b[38;5;241m.\u001b[39mon_chain_start(\n\u001b[1;32m 129\u001b[0m {\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mname\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__class__\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__name__\u001b[39m},\n\u001b[1;32m 130\u001b[0m inputs,\n\u001b[1;32m 131\u001b[0m )\n\u001b[1;32m 132\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 133\u001b[0m outputs \u001b[38;5;241m=\u001b[39m (\n\u001b[0;32m--> 134\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_call\u001b[49m\u001b[43m(\u001b[49m\u001b[43minputs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mrun_manager\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrun_manager\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 135\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m new_arg_supported\n\u001b[1;32m 136\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_call(inputs)\n\u001b[1;32m 137\u001b[0m )\n\u001b[1;32m 138\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (\u001b[38;5;167;01mKeyboardInterrupt\u001b[39;00m, \u001b[38;5;167;01mException\u001b[39;00m) \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 139\u001b[0m run_manager\u001b[38;5;241m.\u001b[39mon_chain_error(e)\n", + "File \u001b[0;32m~/workplace/langchain/langchain/agents/agent.py:934\u001b[0m, in \u001b[0;36mAgentExecutor._call\u001b[0;34m(self, inputs, run_manager)\u001b[0m\n\u001b[1;32m 932\u001b[0m \u001b[38;5;66;03m# We now enter the agent loop (until it returns something).\u001b[39;00m\n\u001b[1;32m 933\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_should_continue(iterations, time_elapsed):\n\u001b[0;32m--> 934\u001b[0m next_step_output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_take_next_step\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 935\u001b[0m \u001b[43m \u001b[49m\u001b[43mname_to_tool_map\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 936\u001b[0m \u001b[43m \u001b[49m\u001b[43mcolor_mapping\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 937\u001b[0m \u001b[43m \u001b[49m\u001b[43minputs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 938\u001b[0m \u001b[43m \u001b[49m\u001b[43mintermediate_steps\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 939\u001b[0m \u001b[43m \u001b[49m\u001b[43mrun_manager\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrun_manager\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 940\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 941\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(next_step_output, AgentFinish):\n\u001b[1;32m 942\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_return(\n\u001b[1;32m 943\u001b[0m next_step_output, intermediate_steps, run_manager\u001b[38;5;241m=\u001b[39mrun_manager\n\u001b[1;32m 944\u001b[0m )\n", + "File \u001b[0;32m~/workplace/langchain/langchain/agents/agent.py:771\u001b[0m, in \u001b[0;36mAgentExecutor._take_next_step\u001b[0;34m(self, name_to_tool_map, color_mapping, inputs, intermediate_steps, run_manager)\u001b[0m\n\u001b[1;32m 769\u001b[0m raise_error \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n\u001b[1;32m 770\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m raise_error:\n\u001b[0;32m--> 771\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m e\n\u001b[1;32m 772\u001b[0m text \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mstr\u001b[39m(e)\n\u001b[1;32m 773\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mhandle_parsing_errors, \u001b[38;5;28mbool\u001b[39m):\n", + "File \u001b[0;32m~/workplace/langchain/langchain/agents/agent.py:760\u001b[0m, in \u001b[0;36mAgentExecutor._take_next_step\u001b[0;34m(self, name_to_tool_map, color_mapping, inputs, intermediate_steps, run_manager)\u001b[0m\n\u001b[1;32m 754\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Take a single step in the thought-action-observation loop.\u001b[39;00m\n\u001b[1;32m 755\u001b[0m \n\u001b[1;32m 756\u001b[0m \u001b[38;5;124;03mOverride this to take control of how the agent makes and acts on choices.\u001b[39;00m\n\u001b[1;32m 757\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 758\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 759\u001b[0m \u001b[38;5;66;03m# Call the LLM to see what to do.\u001b[39;00m\n\u001b[0;32m--> 760\u001b[0m output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43magent\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mplan\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 761\u001b[0m \u001b[43m \u001b[49m\u001b[43mintermediate_steps\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 762\u001b[0m \u001b[43m \u001b[49m\u001b[43mcallbacks\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrun_manager\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_child\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mif\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mrun_manager\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01melse\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 763\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43minputs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 764\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 765\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 766\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mhandle_parsing_errors, \u001b[38;5;28mbool\u001b[39m):\n", + "File \u001b[0;32m~/workplace/langchain/langchain/agents/agent.py:443\u001b[0m, in \u001b[0;36mAgent.plan\u001b[0;34m(self, intermediate_steps, callbacks, **kwargs)\u001b[0m\n\u001b[1;32m 441\u001b[0m full_inputs \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mget_full_inputs(intermediate_steps, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[1;32m 442\u001b[0m full_output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mllm_chain\u001b[38;5;241m.\u001b[39mpredict(callbacks\u001b[38;5;241m=\u001b[39mcallbacks, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mfull_inputs)\n\u001b[0;32m--> 443\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43moutput_parser\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mparse\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfull_output\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/workplace/langchain/langchain/agents/chat/output_parser.py:26\u001b[0m, in \u001b[0;36mChatOutputParser.parse\u001b[0;34m(self, text)\u001b[0m\n\u001b[1;32m 23\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m AgentAction(response[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124maction\u001b[39m\u001b[38;5;124m\"\u001b[39m], response[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124maction_input\u001b[39m\u001b[38;5;124m\"\u001b[39m], text)\n\u001b[1;32m 25\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m:\n\u001b[0;32m---> 26\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m OutputParserException(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mCould not parse LLM output: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mtext\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n", + "\u001b[0;31mOutputParserException\u001b[0m: Could not parse LLM output: I'm sorry, but I cannot provide an answer without an Action. Please provide a valid Action in order for me to assist you." + ] + } + ], + "source": [ + "mrkl.run(\"Who is Leo DiCaprio's girlfriend? No need to add Action\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bf401d5c", + "metadata": {}, + "outputs": [], + "source": [ + "## Default error handling" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "6bfc21ef", + "metadata": {}, + "outputs": [], + "source": [ + "mrkl = initialize_agent(\n", + " tools, \n", + " ChatOpenAI(temperature=0), \n", + " agent=AgentType.CHAT_ZERO_SHOT_REACT_DESCRIPTION, \n", + " verbose=True,\n", + " handle_parsing_errors=True\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "9c181f33", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n", + "\n", + "Observation: Invalid or incomplete response\n", + "Thought:\n", + "Observation: Invalid or incomplete response\n", + "Thought:\u001b[32;1m\u001b[1;3mTo answer the question, I need to use the Search tool.\n", + "Action:\n", + "```\n", + "{\n", + " \"action\": \"Search\",\n", + " \"action_input\": \"Leo DiCaprio girlfriend\"\n", + "}\n", + "```\n", + "\u001b[0m\n", + "Observation: \u001b[36;1m\u001b[1;3mHe went on to date Gisele Bündchen, Bar Refaeli, Blake Lively, Toni Garrn and Nina Agdal, among others, before finally settling down with current girlfriend Camila Morrone, who is 23 years his junior.\u001b[0m\n", + "Thought:\u001b[32;1m\u001b[1;3mThe answer to the question is that Leo DiCaprio's current girlfriend is Camila Morrone. \n", + "Final Answer: Camila Morrone.\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "'Camila Morrone.'" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mrkl.run(\"Who is Leo DiCaprio's girlfriend? No need to add Action\")" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "2b23b0af", + "metadata": {}, + "outputs": [], + "source": [ + "mrkl = initialize_agent(\n", + " tools, \n", + " ChatOpenAI(temperature=0), \n", + " agent=AgentType.CHAT_ZERO_SHOT_REACT_DESCRIPTION, \n", + " verbose=True,\n", + " handle_parsing_errors=\"Check your output and make sure it conforms!\"\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "5d5a3e47", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n", + "\n", + "Observation: Check your output and make sure it conforms!\n", + "Thought:\u001b[32;1m\u001b[1;3mI apologize for the error in my previous response. I will make sure to provide a valid Action this time. \n", + "Final Answer: As I am an AI language model, I do not have access to Leo DiCaprio's current relationship status. However, according to recent news articles, he has been seen with several different women in the past few years, but he has not confirmed any official relationships.\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "\"As I am an AI language model, I do not have access to Leo DiCaprio's current relationship status. However, according to recent news articles, he has been seen with several different women in the past few years, but he has not confirmed any official relationships.\"" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mrkl.run(\"Who is Leo DiCaprio's girlfriend? No need to add Action\")" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "22772981", + "metadata": {}, + "outputs": [], + "source": [ + "def _handle_error(text: str) -> str:\n", + " return text[:50]\n", + "\n", + "mrkl = initialize_agent(\n", + " tools, \n", + " ChatOpenAI(temperature=0), \n", + " agent=AgentType.CHAT_ZERO_SHOT_REACT_DESCRIPTION, \n", + " verbose=True,\n", + " handle_parsing_errors=_handle_error\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "151eb820", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n", + "\n", + "Observation: Could not parse LLM output: I'm sorry, but I canno\n", + "Thought:\n", + "Observation: Could not parse LLM output: I'm sorry for the conf\n", + "Thought:\u001b[32;1m\u001b[1;3mI will use the Search tool to find the answer to the question.\n", + "\n", + "Action:\n", + "```\n", + "{\n", + " \"action\": \"Search\",\n", + " \"action_input\": \"Leo DiCaprio girlfriend\"\n", + "}\n", + "```\n", + "\n", + "\u001b[0m\n", + "Observation: \u001b[36;1m\u001b[1;3mHe went on to date Gisele Bündchen, Bar Refaeli, Blake Lively, Toni Garrn and Nina Agdal, among others, before finally settling down with current girlfriend Camila Morrone, who is 23 years his junior.\u001b[0m\n", + "Thought:\n", + "Observation: Could not parse LLM output: The answer to the ques\n", + "Thought:\u001b[32;1m\u001b[1;3mFinal Answer: Leo DiCaprio's current girlfriend is Camila Morrone.\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "\"Leo DiCaprio's current girlfriend is Camila Morrone.\"" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mrkl.run(\"Who is Leo DiCaprio's girlfriend? No need to add Action\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4aaef878", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.1" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/langchain/agents/agent.py b/langchain/agents/agent.py index 2bb96ce7986ff..778d6f2dfd830 100644 --- a/langchain/agents/agent.py +++ b/langchain/agents/agent.py @@ -773,7 +773,7 @@ def _take_next_step( observation = "Invalid or incomplete response" elif isinstance(self.handle_parsing_errors, str): observation = self.handle_parsing_errors - elif callable(self.handle_parsing_errors): + elif isinstance(self.handle_parsing_errors, Callable): observation = self.handle_parsing_errors(text) else: raise ValueError("Got unexpected type of `handle_parsing_errors`") From 71f38140e9bb7c5e70e879a52e2b6ebc9a4a76bc Mon Sep 17 00:00:00 2001 From: Harrison Chase Date: Wed, 17 May 2023 00:16:43 -0700 Subject: [PATCH 3/5] cr --- langchain/agents/agent.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/langchain/agents/agent.py b/langchain/agents/agent.py index 778d6f2dfd830..2bb96ce7986ff 100644 --- a/langchain/agents/agent.py +++ b/langchain/agents/agent.py @@ -773,7 +773,7 @@ def _take_next_step( observation = "Invalid or incomplete response" elif isinstance(self.handle_parsing_errors, str): observation = self.handle_parsing_errors - elif isinstance(self.handle_parsing_errors, Callable): + elif callable(self.handle_parsing_errors): observation = self.handle_parsing_errors(text) else: raise ValueError("Got unexpected type of `handle_parsing_errors`") From bd319b85188617b1f99dfdbf0b546eb6b3198f7b Mon Sep 17 00:00:00 2001 From: Harrison Chase Date: Wed, 17 May 2023 17:47:13 -0700 Subject: [PATCH 4/5] cr --- .../examples/handle_parsing_errors.ipynb | 4 +-- langchain/agents/agent.py | 30 ++++++++++++++----- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/docs/modules/agents/agent_executors/examples/handle_parsing_errors.ipynb b/docs/modules/agents/agent_executors/examples/handle_parsing_errors.ipynb index f7fdfec7337ee..454d194980cff 100644 --- a/docs/modules/agents/agent_executors/examples/handle_parsing_errors.ipynb +++ b/docs/modules/agents/agent_executors/examples/handle_parsing_errors.ipynb @@ -250,8 +250,8 @@ "metadata": {}, "outputs": [], "source": [ - "def _handle_error(text: str) -> str:\n", - " return text[:50]\n", + "def _handle_error(error) -> str:\n", + " return str(error)[:50]\n", "\n", "mrkl = initialize_agent(\n", " tools, \n", diff --git a/langchain/agents/agent.py b/langchain/agents/agent.py index 2bb96ce7986ff..1e2e6495179e5 100644 --- a/langchain/agents/agent.py +++ b/langchain/agents/agent.py @@ -34,6 +34,7 @@ AgentFinish, BaseMessage, BaseOutputParser, + OutputParserException, ) from langchain.tools.base import BaseTool from langchain.utilities.asyncio import asyncio_timeout @@ -625,7 +626,9 @@ class AgentExecutor(Chain): max_iterations: Optional[int] = 15 max_execution_time: Optional[float] = None early_stopping_method: str = "force" - handle_parsing_errors: Union[bool, str, Callable] = False + handle_parsing_errors: Union[ + bool, str, Callable[[OutputParserException], str] + ] = False @classmethod def from_agent_and_tools( @@ -761,7 +764,7 @@ def _take_next_step( callbacks=run_manager.get_child() if run_manager else None, **inputs, ) - except Exception as e: + except OutputParserException as e: if isinstance(self.handle_parsing_errors, bool): raise_error = not self.handle_parsing_errors else: @@ -774,7 +777,7 @@ def _take_next_step( elif isinstance(self.handle_parsing_errors, str): observation = self.handle_parsing_errors elif callable(self.handle_parsing_errors): - observation = self.handle_parsing_errors(text) + observation = self.handle_parsing_errors(e) else: raise ValueError("Got unexpected type of `handle_parsing_errors`") output = AgentAction("_Exception", observation, text) @@ -846,15 +849,26 @@ async def _atake_next_step( callbacks=run_manager.get_child() if run_manager else None, **inputs, ) - except Exception as e: - if not self.handle_parsing_errors: + except OutputParserException as e: + if isinstance(self.handle_parsing_errors, bool): + raise_error = not self.handle_parsing_errors + else: + raise_error = False + if raise_error: raise e - text = str(e).split("`")[1] - observation = "Invalid or incomplete response" + text = str(e) + if isinstance(self.handle_parsing_errors, bool): + observation = "Invalid or incomplete response" + elif isinstance(self.handle_parsing_errors, str): + observation = self.handle_parsing_errors + elif callable(self.handle_parsing_errors): + observation = self.handle_parsing_errors(e) + else: + raise ValueError("Got unexpected type of `handle_parsing_errors`") output = AgentAction("_Exception", observation, text) tool_run_kwargs = self.agent.tool_run_logging_kwargs() observation = await ExceptionTool().arun( - output.tool, + output.tool_input, verbose=self.verbose, color=None, callbacks=run_manager.get_child() if run_manager else None, From 6be991e24794ffc48f3bb68ef2ae22e79ac77800 Mon Sep 17 00:00:00 2001 From: Harrison Chase Date: Wed, 17 May 2023 21:11:03 -0700 Subject: [PATCH 5/5] cr --- .../examples/handle_parsing_errors.ipynb | 131 ++++++++---------- 1 file changed, 57 insertions(+), 74 deletions(-) diff --git a/docs/modules/agents/agent_executors/examples/handle_parsing_errors.ipynb b/docs/modules/agents/agent_executors/examples/handle_parsing_errors.ipynb index 454d194980cff..dd97f24d35499 100644 --- a/docs/modules/agents/agent_executors/examples/handle_parsing_errors.ipynb +++ b/docs/modules/agents/agent_executors/examples/handle_parsing_errors.ipynb @@ -91,7 +91,7 @@ }, { "ename": "OutputParserException", - "evalue": "Could not parse LLM output: I'm sorry, but I cannot provide an answer without an Action. Please provide a valid Action in order for me to assist you.", + "evalue": "Could not parse LLM output: I'm sorry, but I cannot provide an answer without an Action. Please provide a valid Action in the format specified above.", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", @@ -104,12 +104,12 @@ "File \u001b[0;32m~/workplace/langchain/langchain/chains/base.py:236\u001b[0m, in \u001b[0;36mChain.run\u001b[0;34m(self, callbacks, *args, **kwargs)\u001b[0m\n\u001b[1;32m 234\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(args) \u001b[38;5;241m!=\u001b[39m \u001b[38;5;241m1\u001b[39m:\n\u001b[1;32m 235\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m`run` supports only one positional argument.\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m--> 236\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43margs\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcallbacks\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcallbacks\u001b[49m\u001b[43m)\u001b[49m[\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39moutput_keys[\u001b[38;5;241m0\u001b[39m]]\n\u001b[1;32m 238\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m kwargs \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m args:\n\u001b[1;32m 239\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m(kwargs, callbacks\u001b[38;5;241m=\u001b[39mcallbacks)[\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39moutput_keys[\u001b[38;5;241m0\u001b[39m]]\n", "File \u001b[0;32m~/workplace/langchain/langchain/chains/base.py:140\u001b[0m, in \u001b[0;36mChain.__call__\u001b[0;34m(self, inputs, return_only_outputs, callbacks)\u001b[0m\n\u001b[1;32m 138\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (\u001b[38;5;167;01mKeyboardInterrupt\u001b[39;00m, \u001b[38;5;167;01mException\u001b[39;00m) \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 139\u001b[0m run_manager\u001b[38;5;241m.\u001b[39mon_chain_error(e)\n\u001b[0;32m--> 140\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m e\n\u001b[1;32m 141\u001b[0m run_manager\u001b[38;5;241m.\u001b[39mon_chain_end(outputs)\n\u001b[1;32m 142\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mprep_outputs(inputs, outputs, return_only_outputs)\n", "File \u001b[0;32m~/workplace/langchain/langchain/chains/base.py:134\u001b[0m, in \u001b[0;36mChain.__call__\u001b[0;34m(self, inputs, return_only_outputs, callbacks)\u001b[0m\n\u001b[1;32m 128\u001b[0m run_manager \u001b[38;5;241m=\u001b[39m callback_manager\u001b[38;5;241m.\u001b[39mon_chain_start(\n\u001b[1;32m 129\u001b[0m {\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mname\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__class__\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__name__\u001b[39m},\n\u001b[1;32m 130\u001b[0m inputs,\n\u001b[1;32m 131\u001b[0m )\n\u001b[1;32m 132\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 133\u001b[0m outputs \u001b[38;5;241m=\u001b[39m (\n\u001b[0;32m--> 134\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_call\u001b[49m\u001b[43m(\u001b[49m\u001b[43minputs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mrun_manager\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrun_manager\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 135\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m new_arg_supported\n\u001b[1;32m 136\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_call(inputs)\n\u001b[1;32m 137\u001b[0m )\n\u001b[1;32m 138\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (\u001b[38;5;167;01mKeyboardInterrupt\u001b[39;00m, \u001b[38;5;167;01mException\u001b[39;00m) \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 139\u001b[0m run_manager\u001b[38;5;241m.\u001b[39mon_chain_error(e)\n", - "File \u001b[0;32m~/workplace/langchain/langchain/agents/agent.py:934\u001b[0m, in \u001b[0;36mAgentExecutor._call\u001b[0;34m(self, inputs, run_manager)\u001b[0m\n\u001b[1;32m 932\u001b[0m \u001b[38;5;66;03m# We now enter the agent loop (until it returns something).\u001b[39;00m\n\u001b[1;32m 933\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_should_continue(iterations, time_elapsed):\n\u001b[0;32m--> 934\u001b[0m next_step_output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_take_next_step\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 935\u001b[0m \u001b[43m \u001b[49m\u001b[43mname_to_tool_map\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 936\u001b[0m \u001b[43m \u001b[49m\u001b[43mcolor_mapping\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 937\u001b[0m \u001b[43m \u001b[49m\u001b[43minputs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 938\u001b[0m \u001b[43m \u001b[49m\u001b[43mintermediate_steps\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 939\u001b[0m \u001b[43m \u001b[49m\u001b[43mrun_manager\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrun_manager\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 940\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 941\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(next_step_output, AgentFinish):\n\u001b[1;32m 942\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_return(\n\u001b[1;32m 943\u001b[0m next_step_output, intermediate_steps, run_manager\u001b[38;5;241m=\u001b[39mrun_manager\n\u001b[1;32m 944\u001b[0m )\n", - "File \u001b[0;32m~/workplace/langchain/langchain/agents/agent.py:771\u001b[0m, in \u001b[0;36mAgentExecutor._take_next_step\u001b[0;34m(self, name_to_tool_map, color_mapping, inputs, intermediate_steps, run_manager)\u001b[0m\n\u001b[1;32m 769\u001b[0m raise_error \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n\u001b[1;32m 770\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m raise_error:\n\u001b[0;32m--> 771\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m e\n\u001b[1;32m 772\u001b[0m text \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mstr\u001b[39m(e)\n\u001b[1;32m 773\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mhandle_parsing_errors, \u001b[38;5;28mbool\u001b[39m):\n", - "File \u001b[0;32m~/workplace/langchain/langchain/agents/agent.py:760\u001b[0m, in \u001b[0;36mAgentExecutor._take_next_step\u001b[0;34m(self, name_to_tool_map, color_mapping, inputs, intermediate_steps, run_manager)\u001b[0m\n\u001b[1;32m 754\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Take a single step in the thought-action-observation loop.\u001b[39;00m\n\u001b[1;32m 755\u001b[0m \n\u001b[1;32m 756\u001b[0m \u001b[38;5;124;03mOverride this to take control of how the agent makes and acts on choices.\u001b[39;00m\n\u001b[1;32m 757\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 758\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 759\u001b[0m \u001b[38;5;66;03m# Call the LLM to see what to do.\u001b[39;00m\n\u001b[0;32m--> 760\u001b[0m output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43magent\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mplan\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 761\u001b[0m \u001b[43m \u001b[49m\u001b[43mintermediate_steps\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 762\u001b[0m \u001b[43m \u001b[49m\u001b[43mcallbacks\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrun_manager\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_child\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mif\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mrun_manager\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01melse\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 763\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43minputs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 764\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 765\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 766\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mhandle_parsing_errors, \u001b[38;5;28mbool\u001b[39m):\n", - "File \u001b[0;32m~/workplace/langchain/langchain/agents/agent.py:443\u001b[0m, in \u001b[0;36mAgent.plan\u001b[0;34m(self, intermediate_steps, callbacks, **kwargs)\u001b[0m\n\u001b[1;32m 441\u001b[0m full_inputs \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mget_full_inputs(intermediate_steps, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[1;32m 442\u001b[0m full_output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mllm_chain\u001b[38;5;241m.\u001b[39mpredict(callbacks\u001b[38;5;241m=\u001b[39mcallbacks, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mfull_inputs)\n\u001b[0;32m--> 443\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43moutput_parser\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mparse\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfull_output\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/workplace/langchain/langchain/agents/agent.py:947\u001b[0m, in \u001b[0;36mAgentExecutor._call\u001b[0;34m(self, inputs, run_manager)\u001b[0m\n\u001b[1;32m 945\u001b[0m \u001b[38;5;66;03m# We now enter the agent loop (until it returns something).\u001b[39;00m\n\u001b[1;32m 946\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_should_continue(iterations, time_elapsed):\n\u001b[0;32m--> 947\u001b[0m next_step_output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_take_next_step\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 948\u001b[0m \u001b[43m \u001b[49m\u001b[43mname_to_tool_map\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 949\u001b[0m \u001b[43m \u001b[49m\u001b[43mcolor_mapping\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 950\u001b[0m \u001b[43m \u001b[49m\u001b[43minputs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 951\u001b[0m \u001b[43m \u001b[49m\u001b[43mintermediate_steps\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 952\u001b[0m \u001b[43m \u001b[49m\u001b[43mrun_manager\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrun_manager\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 953\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 954\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(next_step_output, AgentFinish):\n\u001b[1;32m 955\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_return(\n\u001b[1;32m 956\u001b[0m next_step_output, intermediate_steps, run_manager\u001b[38;5;241m=\u001b[39mrun_manager\n\u001b[1;32m 957\u001b[0m )\n", + "File \u001b[0;32m~/workplace/langchain/langchain/agents/agent.py:773\u001b[0m, in \u001b[0;36mAgentExecutor._take_next_step\u001b[0;34m(self, name_to_tool_map, color_mapping, inputs, intermediate_steps, run_manager)\u001b[0m\n\u001b[1;32m 771\u001b[0m raise_error \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n\u001b[1;32m 772\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m raise_error:\n\u001b[0;32m--> 773\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m e\n\u001b[1;32m 774\u001b[0m text \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mstr\u001b[39m(e)\n\u001b[1;32m 775\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mhandle_parsing_errors, \u001b[38;5;28mbool\u001b[39m):\n", + "File \u001b[0;32m~/workplace/langchain/langchain/agents/agent.py:762\u001b[0m, in \u001b[0;36mAgentExecutor._take_next_step\u001b[0;34m(self, name_to_tool_map, color_mapping, inputs, intermediate_steps, run_manager)\u001b[0m\n\u001b[1;32m 756\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Take a single step in the thought-action-observation loop.\u001b[39;00m\n\u001b[1;32m 757\u001b[0m \n\u001b[1;32m 758\u001b[0m \u001b[38;5;124;03mOverride this to take control of how the agent makes and acts on choices.\u001b[39;00m\n\u001b[1;32m 759\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 760\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 761\u001b[0m \u001b[38;5;66;03m# Call the LLM to see what to do.\u001b[39;00m\n\u001b[0;32m--> 762\u001b[0m output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43magent\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mplan\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 763\u001b[0m \u001b[43m \u001b[49m\u001b[43mintermediate_steps\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 764\u001b[0m \u001b[43m \u001b[49m\u001b[43mcallbacks\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrun_manager\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_child\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mif\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mrun_manager\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01melse\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 765\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43minputs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 766\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 767\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m OutputParserException \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 768\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mhandle_parsing_errors, \u001b[38;5;28mbool\u001b[39m):\n", + "File \u001b[0;32m~/workplace/langchain/langchain/agents/agent.py:444\u001b[0m, in \u001b[0;36mAgent.plan\u001b[0;34m(self, intermediate_steps, callbacks, **kwargs)\u001b[0m\n\u001b[1;32m 442\u001b[0m full_inputs \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mget_full_inputs(intermediate_steps, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[1;32m 443\u001b[0m full_output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mllm_chain\u001b[38;5;241m.\u001b[39mpredict(callbacks\u001b[38;5;241m=\u001b[39mcallbacks, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mfull_inputs)\n\u001b[0;32m--> 444\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43moutput_parser\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mparse\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfull_output\u001b[49m\u001b[43m)\u001b[49m\n", "File \u001b[0;32m~/workplace/langchain/langchain/agents/chat/output_parser.py:26\u001b[0m, in \u001b[0;36mChatOutputParser.parse\u001b[0;34m(self, text)\u001b[0m\n\u001b[1;32m 23\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m AgentAction(response[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124maction\u001b[39m\u001b[38;5;124m\"\u001b[39m], response[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124maction_input\u001b[39m\u001b[38;5;124m\"\u001b[39m], text)\n\u001b[1;32m 25\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m:\n\u001b[0;32m---> 26\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m OutputParserException(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mCould not parse LLM output: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mtext\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n", - "\u001b[0;31mOutputParserException\u001b[0m: Could not parse LLM output: I'm sorry, but I cannot provide an answer without an Action. Please provide a valid Action in order for me to assist you." + "\u001b[0;31mOutputParserException\u001b[0m: Could not parse LLM output: I'm sorry, but I cannot provide an answer without an Action. Please provide a valid Action in the format specified above." ] } ], @@ -118,13 +118,13 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "bf401d5c", + "cell_type": "markdown", + "id": "72687d56", "metadata": {}, - "outputs": [], "source": [ - "## Default error handling" + "## Default error handling\n", + "\n", + "Handle errors with `Invalid or incomplete response`" ] }, { @@ -160,18 +160,18 @@ "Observation: Invalid or incomplete response\n", "Thought:\n", "Observation: Invalid or incomplete response\n", - "Thought:\u001b[32;1m\u001b[1;3mTo answer the question, I need to use the Search tool.\n", + "Thought:\u001b[32;1m\u001b[1;3mSearch for Leo DiCaprio's current girlfriend\n", "Action:\n", "```\n", "{\n", " \"action\": \"Search\",\n", - " \"action_input\": \"Leo DiCaprio girlfriend\"\n", + " \"action_input\": \"Leo DiCaprio current girlfriend\"\n", "}\n", "```\n", "\u001b[0m\n", - "Observation: \u001b[36;1m\u001b[1;3mHe went on to date Gisele Bündchen, Bar Refaeli, Blake Lively, Toni Garrn and Nina Agdal, among others, before finally settling down with current girlfriend Camila Morrone, who is 23 years his junior.\u001b[0m\n", - "Thought:\u001b[32;1m\u001b[1;3mThe answer to the question is that Leo DiCaprio's current girlfriend is Camila Morrone. \n", - "Final Answer: Camila Morrone.\u001b[0m\n", + "Observation: \u001b[36;1m\u001b[1;3mJust Jared on Instagram: “Leonardo DiCaprio & girlfriend Camila Morrone couple up for a lunch date!\u001b[0m\n", + "Thought:\u001b[32;1m\u001b[1;3mCamila Morrone is currently Leo DiCaprio's girlfriend\n", + "Final Answer: Camila Morrone\u001b[0m\n", "\n", "\u001b[1m> Finished chain.\u001b[0m\n" ] @@ -179,7 +179,7 @@ { "data": { "text/plain": [ - "'Camila Morrone.'" + "'Camila Morrone'" ] }, "execution_count": 6, @@ -191,6 +191,16 @@ "mrkl.run(\"Who is Leo DiCaprio's girlfriend? No need to add Action\")" ] }, + { + "cell_type": "markdown", + "id": "6613cc9c", + "metadata": {}, + "source": [ + "## Custom Error Message\n", + "\n", + "You can easily customize the message to use when there are parsing errors" + ] + }, { "cell_type": "code", "execution_count": 7, @@ -209,7 +219,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "id": "5d5a3e47", "metadata": {}, "outputs": [ @@ -222,21 +232,23 @@ "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n", "\n", "Observation: Check your output and make sure it conforms!\n", - "Thought:\u001b[32;1m\u001b[1;3mI apologize for the error in my previous response. I will make sure to provide a valid Action this time. \n", - "Final Answer: As I am an AI language model, I do not have access to Leo DiCaprio's current relationship status. However, according to recent news articles, he has been seen with several different women in the past few years, but he has not confirmed any official relationships.\u001b[0m\n", + "Thought:\n", + "Observation: Check your output and make sure it conforms!\n", + "Thought:\u001b[32;1m\u001b[1;3mI'm sorry for the confusion. However, as the question is about a current event, I can use the Search tool to find the answer.\n", + "Action:\n", + "```\n", + "{\n", + " \"action\": \"Search\",\n", + " \"action_input\": \"Leo DiCaprio girlfriend\"\n", + "}\n", + "```\n", + "\u001b[0m\n", + "Observation: \u001b[36;1m\u001b[1;3mHe went on to date Gisele Bündchen, Bar Refaeli, Blake Lively, Toni Garrn and Nina Agdal, among others, before finally settling down with current girlfriend Camila Morrone, who is 23 years his junior.\u001b[0m\n", + "Thought:\u001b[32;1m\u001b[1;3mThe answer to the question is Camila Morrone. \n", + "Final Answer: Camila Morrone.\u001b[0m\n", "\n", "\u001b[1m> Finished chain.\u001b[0m\n" ] - }, - { - "data": { - "text/plain": [ - "\"As I am an AI language model, I do not have access to Leo DiCaprio's current relationship status. However, according to recent news articles, he has been seen with several different women in the past few years, but he has not confirmed any official relationships.\"" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" } ], "source": [ @@ -245,7 +257,19 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, + "id": "65de0bed", + "metadata": {}, + "outputs": [], + "source": [ + "## Custom Error Function\n", + "\n", + "You can also customize the error to be a fun" + ] + }, + { + "cell_type": "code", + "execution_count": null, "id": "22772981", "metadata": {}, "outputs": [], @@ -264,51 +288,10 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "id": "151eb820", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n", - "\n", - "Observation: Could not parse LLM output: I'm sorry, but I canno\n", - "Thought:\n", - "Observation: Could not parse LLM output: I'm sorry for the conf\n", - "Thought:\u001b[32;1m\u001b[1;3mI will use the Search tool to find the answer to the question.\n", - "\n", - "Action:\n", - "```\n", - "{\n", - " \"action\": \"Search\",\n", - " \"action_input\": \"Leo DiCaprio girlfriend\"\n", - "}\n", - "```\n", - "\n", - "\u001b[0m\n", - "Observation: \u001b[36;1m\u001b[1;3mHe went on to date Gisele Bündchen, Bar Refaeli, Blake Lively, Toni Garrn and Nina Agdal, among others, before finally settling down with current girlfriend Camila Morrone, who is 23 years his junior.\u001b[0m\n", - "Thought:\n", - "Observation: Could not parse LLM output: The answer to the ques\n", - "Thought:\u001b[32;1m\u001b[1;3mFinal Answer: Leo DiCaprio's current girlfriend is Camila Morrone.\u001b[0m\n", - "\n", - "\u001b[1m> Finished chain.\u001b[0m\n" - ] - }, - { - "data": { - "text/plain": [ - "\"Leo DiCaprio's current girlfriend is Camila Morrone.\"" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "mrkl.run(\"Who is Leo DiCaprio's girlfriend? No need to add Action\")" ]