From 18ec22fe56049aaea446406daab6d66d172dd48f Mon Sep 17 00:00:00 2001 From: Zander Chase <130414180+vowelparrot@users.noreply.github.com> Date: Sat, 29 Apr 2023 15:29:08 -0700 Subject: [PATCH] Remove multi-input tool section (#3810) Moving to new notebook. Will re-intro w/ new agent --- docs/modules/agents/tools/custom_tools.ipynb | 149 +------------------ 1 file changed, 1 insertion(+), 148 deletions(-) diff --git a/docs/modules/agents/tools/custom_tools.ipynb b/docs/modules/agents/tools/custom_tools.ipynb index b34cd90d..050580df 100644 --- a/docs/modules/agents/tools/custom_tools.ipynb +++ b/docs/modules/agents/tools/custom_tools.ipynb @@ -674,153 +674,6 @@ "source": [ "agent.run(\"whats 2**.12\")" ] - }, - { - "cell_type": "markdown", - "id": "8aa3c353-bd89-467c-9c27-b83a90cd4daa", - "metadata": {}, - "source": [ - "## Multi-argument tools\n", - "\n", - "Many functions expect structured inputs. These can also be supported using the Tool decorator or by directly subclassing `BaseTool`! We have to modify the LLM's OutputParser to map its string output to a dictionary to pass to the action, however." - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "id": "537bc628", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "from typing import Optional, Union\n", - "\n", - "@tool\n", - "def custom_search(k: int, query: str, other_arg: Optional[str] = None):\n", - " \"\"\"The custom search function.\"\"\"\n", - " return f\"Here are the results for the custom search: k={k}, query={query}, other_arg={other_arg}\"" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "id": "d5c992cf-776a-40cd-a6c4-e7cf65ea709e", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "import re\n", - "from langchain.schema import (\n", - " AgentAction,\n", - " AgentFinish,\n", - ")\n", - "from langchain.agents import AgentOutputParser\n", - "\n", - "# We will add a custom parser to map the arguments to a dictionary\n", - "class CustomOutputParser(AgentOutputParser):\n", - " \n", - " def parse_tool_input(self, action_input: str) -> dict:\n", - " # Regex pattern to match arguments and their values\n", - " pattern = r\"(\\w+)\\s*=\\s*(None|\\\"[^\\\"]*\\\"|\\d+)\"\n", - " matches = re.findall(pattern, action_input)\n", - " \n", - " if not matches:\n", - " raise ValueError(f\"Could not parse action input: `{action_input}`\")\n", - "\n", - " # Create a dictionary with the parsed arguments and their values\n", - " parsed_input = {}\n", - " for arg, value in matches:\n", - " if value == \"None\":\n", - " parsed_value = None\n", - " elif value.isdigit():\n", - " parsed_value = int(value)\n", - " else:\n", - " parsed_value = value.strip('\"')\n", - " parsed_input[arg] = parsed_value\n", - "\n", - " return parsed_input\n", - " \n", - " def parse(self, llm_output: str) -> Union[AgentAction, AgentFinish]:\n", - " # Check if agent should finish\n", - " if \"Final Answer:\" in llm_output:\n", - " return AgentFinish(\n", - " # Return values is generally always a dictionary with a single `output` key\n", - " # It is not recommended to try anything else at the moment :)\n", - " return_values={\"output\": llm_output.split(\"Final Answer:\")[-1].strip()},\n", - " log=llm_output,\n", - " )\n", - " # Parse out the action and action input\n", - " regex = r\"Action\\s*\\d*\\s*:(.*?)\\nAction\\s*\\d*\\s*Input\\s*\\d*\\s*:[\\s]*(.*)\"\n", - " match = re.search(regex, llm_output, re.DOTALL)\n", - " if not match:\n", - " raise ValueError(f\"Could not parse LLM output: `{llm_output}`\")\n", - " action = match.group(1).strip()\n", - " action_input = match.group(2)\n", - " tool_input = self.parse_tool_input(action_input)\n", - " # Return the action and action \n", - " return AgentAction(tool=action, tool_input=tool_input, log=llm_output)" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "id": "68269547-1482-4138-a6ea-58f00b4a9548", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "llm = OpenAI(temperature=0)\n", - "agent = initialize_agent([custom_search], llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True, agent_kwargs={\"output_parser\": CustomOutputParser()})" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "id": "0947835a-691c-4f51-b8f4-6744e0e48ab1", - "metadata": { - "tags": [] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n", - "\u001b[32;1m\u001b[1;3m I need to use a search function to find the answer\n", - "Action: custom_search\n", - "Action Input: k=1, query=\"me\"\u001b[0m\u001b[36;1m\u001b[1;3mHere are the results for the custom search: k=1, query=me, other_arg=None\u001b[0m\u001b[32;1m\u001b[1;3m I now know the final answer\n", - "Final Answer: The results of the custom search for k=1, query=me, other_arg=None.\u001b[0m\n", - "\n", - "\u001b[1m> Finished chain.\u001b[0m\n" - ] - }, - { - "data": { - "text/plain": [ - "'The results of the custom search for k=1, query=me, other_arg=None.'" - ] - }, - "execution_count": 27, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "agent.run(\"Search for me and tell me whatever it says\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "caf39c66-102b-42c1-baf2-777a49886ce4", - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { @@ -839,7 +692,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.1" + "version": "3.11.2" }, "vscode": { "interpreter": {