diff --git a/docs/modules/agents/examples/human_tools.ipynb b/docs/modules/agents/examples/human_tools.ipynb new file mode 100644 index 0000000000..49fdc65759 --- /dev/null +++ b/docs/modules/agents/examples/human_tools.ipynb @@ -0,0 +1,344 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Human as a tool\n", + "\n", + "Human are AGI so they can certainly be used as a tool to help out AI agent \n", + "when it is confused." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "from langchain.chat_models import ChatOpenAI\n", + "from langchain.llms import OpenAI\n", + "from langchain.agents import load_tools, initialize_agent\n", + "\n", + "llm = ChatOpenAI(temperature=0.0)\n", + "math_llm = OpenAI(temperature=0.0)\n", + "tools = load_tools(\n", + " [\"human\", \"llm-math\"], \n", + " llm=math_llm, \n", + " prompt_func=lambda s: sys.stdout.write(s + \"\\n\"), \n", + " input_func=input,\n", + ")\n", + "\n", + "agent_chain = initialize_agent(\n", + " tools,\n", + " llm,\n", + " agent=\"zero-shot-react-description\",\n", + " verbose=True,\n", + ")" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the above code you can see the tool takes input directly from command line.\n", + "You can customize `prompt_func` and `input_func` according to your need." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n", + "\n", + "\n", + "\u001b[1m> Entering new LLMChain chain...\u001b[0m\n", + "Prompt after formatting:\n", + "\u001b[32;1m\u001b[1;3mAnswer the following questions as best you can. You have access to the following tools:\n", + "\n", + "Human: A human. Useful for clarification, confirmation, or anything other tools cannot help.Input should be a question you need help with.\n", + "Calculator: Useful for when you need to answer questions about math.\n", + "\n", + "Use the following format:\n", + "\n", + "Question: the input question you must answer\n", + "Thought: you should always think about what to do\n", + "Action: the action to take, should be one of [Human, Calculator]\n", + "Action Input: the input to the action\n", + "Observation: the result of the action\n", + "... (this Thought/Action/Action Input/Observation can repeat N times)\n", + "Thought: I now know the final answer\n", + "Final Answer: the final answer to the original input question\n", + "\n", + "Begin!\n", + "\n", + "Question: What is Eric Zhu's birthday?\n", + "Thought:\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\u001b[32;1m\u001b[1;3mI don't have any information on Eric Zhu's birthday, so I'll need to ask a human.\n", + "Action: Human\n", + "Action Input: \"Do you know Eric Zhu's birthday?\"\u001b[0mDo you know Eric Zhu's birthday?\n", + "\n", + "Observation: \u001b[36;1m\u001b[1;3mYes\u001b[0m\n", + "Thought:\n", + "\n", + "\u001b[1m> Entering new LLMChain chain...\u001b[0m\n", + "Prompt after formatting:\n", + "\u001b[32;1m\u001b[1;3mAnswer the following questions as best you can. You have access to the following tools:\n", + "\n", + "Human: A human. Useful for clarification, confirmation, or anything other tools cannot help.Input should be a question you need help with.\n", + "Calculator: Useful for when you need to answer questions about math.\n", + "\n", + "Use the following format:\n", + "\n", + "Question: the input question you must answer\n", + "Thought: you should always think about what to do\n", + "Action: the action to take, should be one of [Human, Calculator]\n", + "Action Input: the input to the action\n", + "Observation: the result of the action\n", + "... (this Thought/Action/Action Input/Observation can repeat N times)\n", + "Thought: I now know the final answer\n", + "Final Answer: the final answer to the original input question\n", + "\n", + "Begin!\n", + "\n", + "Question: What is Eric Zhu's birthday?\n", + "Thought:I don't have any information on Eric Zhu's birthday, so I'll need to ask a human.\n", + "Action: Human\n", + "Action Input: \"Do you know Eric Zhu's birthday?\"\n", + "Observation: Yes\n", + "Thought:\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\u001b[32;1m\u001b[1;3mGreat, now I just need to wait for the human to provide the answer.\n", + "Action: Human\n", + "Action Input: \"What is Eric Zhu's birthday?\"\u001b[0mWhat is Eric Zhu's birthday?\n", + "\n", + "Observation: \u001b[36;1m\u001b[1;3mIt's today\u001b[0m\n", + "Thought:\n", + "\n", + "\u001b[1m> Entering new LLMChain chain...\u001b[0m\n", + "Prompt after formatting:\n", + "\u001b[32;1m\u001b[1;3mAnswer the following questions as best you can. You have access to the following tools:\n", + "\n", + "Human: A human. Useful for clarification, confirmation, or anything other tools cannot help.Input should be a question you need help with.\n", + "Calculator: Useful for when you need to answer questions about math.\n", + "\n", + "Use the following format:\n", + "\n", + "Question: the input question you must answer\n", + "Thought: you should always think about what to do\n", + "Action: the action to take, should be one of [Human, Calculator]\n", + "Action Input: the input to the action\n", + "Observation: the result of the action\n", + "... (this Thought/Action/Action Input/Observation can repeat N times)\n", + "Thought: I now know the final answer\n", + "Final Answer: the final answer to the original input question\n", + "\n", + "Begin!\n", + "\n", + "Question: What is Eric Zhu's birthday?\n", + "Thought:I don't have any information on Eric Zhu's birthday, so I'll need to ask a human.\n", + "Action: Human\n", + "Action Input: \"Do you know Eric Zhu's birthday?\"\n", + "Observation: Yes\n", + "Thought:Great, now I just need to wait for the human to provide the answer.\n", + "Action: Human\n", + "Action Input: \"What is Eric Zhu's birthday?\"\n", + "Observation: It's today\n", + "Thought:\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\u001b[32;1m\u001b[1;3mI need to confirm if the human is sure about the answer.\n", + "Action: Human\n", + "Action Input: \"Are you sure it's today?\"\u001b[0mAre you sure it's today?\n", + "\n", + "Observation: \u001b[36;1m\u001b[1;3m\u001b[0m\n", + "Thought:\n", + "\n", + "\u001b[1m> Entering new LLMChain chain...\u001b[0m\n", + "Prompt after formatting:\n", + "\u001b[32;1m\u001b[1;3mAnswer the following questions as best you can. You have access to the following tools:\n", + "\n", + "Human: A human. Useful for clarification, confirmation, or anything other tools cannot help.Input should be a question you need help with.\n", + "Calculator: Useful for when you need to answer questions about math.\n", + "\n", + "Use the following format:\n", + "\n", + "Question: the input question you must answer\n", + "Thought: you should always think about what to do\n", + "Action: the action to take, should be one of [Human, Calculator]\n", + "Action Input: the input to the action\n", + "Observation: the result of the action\n", + "... (this Thought/Action/Action Input/Observation can repeat N times)\n", + "Thought: I now know the final answer\n", + "Final Answer: the final answer to the original input question\n", + "\n", + "Begin!\n", + "\n", + "Question: What is Eric Zhu's birthday?\n", + "Thought:I don't have any information on Eric Zhu's birthday, so I'll need to ask a human.\n", + "Action: Human\n", + "Action Input: \"Do you know Eric Zhu's birthday?\"\n", + "Observation: Yes\n", + "Thought:Great, now I just need to wait for the human to provide the answer.\n", + "Action: Human\n", + "Action Input: \"What is Eric Zhu's birthday?\"\n", + "Observation: It's today\n", + "Thought:I need to confirm if the human is sure about the answer.\n", + "Action: Human\n", + "Action Input: \"Are you sure it's today?\"\n", + "Observation: \n", + "Thought:\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\u001b[32;1m\u001b[1;3mThe human confirmed that it's today, but I still need to verify it with a calculator.\n", + "Action: Calculator\n", + "Action Input: Today's date\u001b[0m\n", + "\n", + "\u001b[1m> Entering new LLMMathChain chain...\u001b[0m\n", + "Today's date\n", + "\n", + "\u001b[1m> Entering new LLMChain chain...\u001b[0m\n", + "Prompt after formatting:\n", + "\u001b[32;1m\u001b[1;3mTranslate a math problem into Python code that can be executed in Python 3 REPL. Use the output of running this code to answer the question.\n", + "\n", + "Question: ${Question with math problem.}\n", + "```python\n", + "${Code that solves the problem and prints the solution}\n", + "```\n", + "```output\n", + "${Output of running the code}\n", + "```\n", + "Answer: ${Answer}\n", + "\n", + "Begin.\n", + "\n", + "Question: What is 37593 * 67?\n", + "\n", + "```python\n", + "print(37593 * 67)\n", + "```\n", + "```output\n", + "2518731\n", + "```\n", + "Answer: 2518731\n", + "\n", + "Question: Today's date\n", + "\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\u001b[32;1m\u001b[1;3m\n", + "```python\n", + "import datetime\n", + "\n", + "print(datetime.date.today())\n", + "```\n", + "\u001b[0m\n", + "Answer: \u001b[33;1m\u001b[1;3m2023-03-22\n", + "\u001b[0m\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\n", + "Observation: \u001b[33;1m\u001b[1;3mAnswer: 2023-03-22\n", + "\u001b[0m\n", + "Thought:\n", + "\n", + "\u001b[1m> Entering new LLMChain chain...\u001b[0m\n", + "Prompt after formatting:\n", + "\u001b[32;1m\u001b[1;3mAnswer the following questions as best you can. You have access to the following tools:\n", + "\n", + "Human: A human. Useful for clarification, confirmation, or anything other tools cannot help.Input should be a question you need help with.\n", + "Calculator: Useful for when you need to answer questions about math.\n", + "\n", + "Use the following format:\n", + "\n", + "Question: the input question you must answer\n", + "Thought: you should always think about what to do\n", + "Action: the action to take, should be one of [Human, Calculator]\n", + "Action Input: the input to the action\n", + "Observation: the result of the action\n", + "... (this Thought/Action/Action Input/Observation can repeat N times)\n", + "Thought: I now know the final answer\n", + "Final Answer: the final answer to the original input question\n", + "\n", + "Begin!\n", + "\n", + "Question: What is Eric Zhu's birthday?\n", + "Thought:I don't have any information on Eric Zhu's birthday, so I'll need to ask a human.\n", + "Action: Human\n", + "Action Input: \"Do you know Eric Zhu's birthday?\"\n", + "Observation: Yes\n", + "Thought:Great, now I just need to wait for the human to provide the answer.\n", + "Action: Human\n", + "Action Input: \"What is Eric Zhu's birthday?\"\n", + "Observation: It's today\n", + "Thought:I need to confirm if the human is sure about the answer.\n", + "Action: Human\n", + "Action Input: \"Are you sure it's today?\"\n", + "Observation: \n", + "Thought:The human confirmed that it's today, but I still need to verify it with a calculator.\n", + "Action: Calculator\n", + "Action Input: Today's date\n", + "Observation: Answer: 2023-03-22\n", + "\n", + "Thought:\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n", + "\u001b[32;1m\u001b[1;3mI now know the final answer\n", + "Final Answer: Eric Zhu's birthday is March 22, 2023.\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "\"Eric Zhu's birthday is March 22, 2023.\"" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\n", + "agent_chain.run(\"What is Eric Zhu's birthday?\")\n", + "# Answer with \"it is today.\"" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "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.11.2" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/langchain/agents/load_tools.py b/langchain/agents/load_tools.py index 3ae824aebc..1ca5a86e85 100644 --- a/langchain/agents/load_tools.py +++ b/langchain/agents/load_tools.py @@ -13,6 +13,7 @@ from langchain.requests import RequestsWrapper from langchain.tools.base import BaseTool from langchain.tools.bing_search.tool import BingSearchRun from langchain.tools.google_search.tool import GoogleSearchResults, GoogleSearchRun +from langchain.tools.human.tool import HumanInputRun from langchain.tools.python.tool import PythonREPLTool from langchain.tools.requests.tool import RequestsGetTool from langchain.tools.wikipedia.tool import WikipediaQueryRun @@ -177,6 +178,10 @@ def _get_bing_search(**kwargs: Any) -> BaseTool: return BingSearchRun(api_wrapper=BingSearchAPIWrapper(**kwargs)) +def _get_human_tool(**kwargs: Any) -> BaseTool: + return HumanInputRun(**kwargs) + + _EXTRA_LLM_TOOLS = { "news-api": (_get_news_api, ["news_api_key"]), "tmdb-api": (_get_tmdb_api, ["tmdb_bearer_token"]), @@ -195,6 +200,7 @@ _EXTRA_OPTIONAL_TOOLS = { "serpapi": (_get_serpapi, ["serpapi_api_key", "aiosession"]), "searx-search": (_get_searx_search, ["searx_host"]), "wikipedia": (_get_wikipedia, ["top_k_results"]), + "human": (_get_human_tool, ["prompt_func", "input_func"]), } diff --git a/langchain/tools/human/__init__.py b/langchain/tools/human/__init__.py new file mode 100644 index 0000000000..704a29da0b --- /dev/null +++ b/langchain/tools/human/__init__.py @@ -0,0 +1 @@ +"""Tool for asking for human input.""" diff --git a/langchain/tools/human/tool.py b/langchain/tools/human/tool.py new file mode 100644 index 0000000000..1b710c0a03 --- /dev/null +++ b/langchain/tools/human/tool.py @@ -0,0 +1,27 @@ +"""Tool for asking human input.""" + +from typing import Callable + +from langchain.tools.base import BaseTool + + +class HumanInputRun(BaseTool): + """Tool that adds the capability to ask user for input.""" + + name = "Human" + description = ( + "A human. " + "Useful for clarification, confirmation, or anything other tools cannot help. " + "Input should be a question you need help with." + ) + prompt_func: Callable[[str], None] + input_func: Callable + + def _run(self, query: str) -> str: + """Use the Human input tool.""" + self.prompt_func(query) + return self.input_func() + + async def _arun(self, query: str) -> str: + """Use the Human tool asynchronously.""" + raise NotImplementedError("Human tool does not support async")