diff --git a/examples/natbot.py b/examples/natbot.py index 9f380bf787f..59c696ac732 100644 --- a/examples/natbot.py +++ b/examples/natbot.py @@ -46,7 +46,7 @@ if __name__ == "__main__": try: while True: browser_content = "\n".join(_crawler.crawl()) - llm_command = nat_bot_chain.run(_crawler.page.url, browser_content) + llm_command = nat_bot_chain.execute(_crawler.page.url, browser_content) if not quiet: print("URL: " + _crawler.page.url) print("Objective: " + objective) diff --git a/examples/sqlite.ipynb b/examples/sqlite.ipynb index 5e7e4c6a9f4..9f8be5a416e 100644 --- a/examples/sqlite.ipynb +++ b/examples/sqlite.ipynb @@ -58,7 +58,7 @@ } ], "source": [ - "db_chain.query(\"How many employees are there?\")" + "db_chain.run(\"How many employees are there?\")" ] }, { diff --git a/examples/vector_db_qa.ipynb b/examples/vector_db_qa.ipynb index c6ec0a573c0..9e774d26601 100644 --- a/examples/vector_db_qa.ipynb +++ b/examples/vector_db_qa.ipynb @@ -86,7 +86,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.7" + "version": "3.7.6" } }, "nbformat": 4, diff --git a/langchain/chains/base.py b/langchain/chains/base.py index dfc48c59b95..15827f6577c 100644 --- a/langchain/chains/base.py +++ b/langchain/chains/base.py @@ -35,7 +35,7 @@ class Chain(BaseModel, ABC): ) @abstractmethod - def _run(self, inputs: Dict[str, str]) -> Dict[str, str]: + def _call(self, inputs: Dict[str, str]) -> Dict[str, str]: """Run the logic of this chain and return the output.""" def __call__(self, inputs: Dict[str, Any]) -> Dict[str, str]: @@ -43,8 +43,22 @@ class Chain(BaseModel, ABC): self._validate_inputs(inputs) if self.verbose: print("\n\n\033[1m> Entering new chain...\033[0m") - outputs = self._run(inputs) + outputs = self._call(inputs) if self.verbose: print("\n\033[1m> Finished chain.\033[0m") self._validate_outputs(outputs) return {**inputs, **outputs} + + def run(self, text: str) -> str: + """Run text in, text out (if applicable).""" + if len(self.input_keys) != 1: + raise ValueError( + f"`run` not supported when there is not exactly " + f"one input key, got {self.input_keys}." + ) + if len(self.output_keys) != 1: + raise ValueError( + f"`run` not supported when there is not exactly " + f"one output key, got {self.output_keys}." + ) + return self({self.input_keys[0]: text})[self.output_keys[0]] diff --git a/langchain/chains/llm.py b/langchain/chains/llm.py index c73db42e907..fe173a38e56 100644 --- a/langchain/chains/llm.py +++ b/langchain/chains/llm.py @@ -48,7 +48,7 @@ class LLMChain(Chain, BaseModel): """ return [self.output_key] - def _run(self, inputs: Dict[str, Any]) -> Dict[str, str]: + def _call(self, inputs: Dict[str, Any]) -> Dict[str, str]: selected_inputs = {k: inputs[k] for k in self.prompt.input_variables} prompt = self.prompt.format(**selected_inputs) diff --git a/langchain/chains/llm_math/base.py b/langchain/chains/llm_math/base.py index 6da17545347..8827230179f 100644 --- a/langchain/chains/llm_math/base.py +++ b/langchain/chains/llm_math/base.py @@ -48,7 +48,7 @@ class LLMMathChain(Chain, BaseModel): """ return [self.output_key] - def _run(self, inputs: Dict[str, str]) -> Dict[str, str]: + def _call(self, inputs: Dict[str, str]) -> Dict[str, str]: llm_executor = LLMChain(prompt=PROMPT, llm=self.llm) python_executor = PythonChain() chained_input = ChainedInput(inputs[self.input_key], verbose=self.verbose) @@ -66,19 +66,3 @@ class LLMMathChain(Chain, BaseModel): else: raise ValueError(f"unknown format from LLM: {t}") return {self.output_key: answer} - - def run(self, question: str) -> str: - """Understand user question and execute math in Python if necessary. - - Args: - question: User question that contains a math question to parse and answer. - - Returns: - The answer to the question. - - Example: - .. code-block:: python - - answer = llm_math.run("What is one plus one?") - """ - return self({self.input_key: question})[self.output_key] diff --git a/langchain/chains/mapreduce.py b/langchain/chains/mapreduce.py index 26674442f91..0a88f945c61 100644 --- a/langchain/chains/mapreduce.py +++ b/langchain/chains/mapreduce.py @@ -57,7 +57,7 @@ class MapReduceChain(Chain, BaseModel): """ return [self.output_key] - def _run(self, inputs: Dict[str, str]) -> Dict[str, str]: + def _call(self, inputs: Dict[str, str]) -> Dict[str, str]: # Split the larger text into smaller chunks. docs = self.text_splitter.split_text( inputs[self.input_key], @@ -76,7 +76,3 @@ class MapReduceChain(Chain, BaseModel): inputs = {self.reduce_llm.prompt.input_variables[0]: summary_str} output = self.reduce_llm.predict(**inputs) return {self.output_key: output} - - def run(self, text: str) -> str: - """Run the map-reduce logic on the input text.""" - return self({self.input_key: text})[self.output_key] diff --git a/langchain/chains/mrkl/base.py b/langchain/chains/mrkl/base.py index 00c797d77bd..38d04048c02 100644 --- a/langchain/chains/mrkl/base.py +++ b/langchain/chains/mrkl/base.py @@ -147,7 +147,7 @@ class MRKLChain(Chain, BaseModel): """ return [self.output_key] - def _run(self, inputs: Dict[str, str]) -> Dict[str, str]: + def _call(self, inputs: Dict[str, str]) -> Dict[str, str]: llm_chain = LLMChain(llm=self.llm, prompt=self.prompt) chained_input = ChainedInput( f"{inputs[self.input_key]}\nThought:", verbose=self.verbose @@ -168,7 +168,3 @@ class MRKLChain(Chain, BaseModel): chained_input.add("\nObservation: ") chained_input.add(ca, color=color_mapping[action]) chained_input.add("\nThought:") - - def run(self, _input: str) -> str: - """Run input through the MRKL system.""" - return self({self.input_key: _input})[self.output_key] diff --git a/langchain/chains/natbot/base.py b/langchain/chains/natbot/base.py index 7812329cb84..67c69363fad 100644 --- a/langchain/chains/natbot/base.py +++ b/langchain/chains/natbot/base.py @@ -57,7 +57,7 @@ class NatBotChain(Chain, BaseModel): """ return [self.output_key] - def _run(self, inputs: Dict[str, str]) -> Dict[str, str]: + def _call(self, inputs: Dict[str, str]) -> Dict[str, str]: llm_executor = LLMChain(prompt=PROMPT, llm=self.llm) url = inputs[self.input_url_key] browser_content = inputs[self.input_browser_content_key] @@ -71,7 +71,7 @@ class NatBotChain(Chain, BaseModel): self.previous_command = llm_cmd return {self.output_key: llm_cmd} - def run(self, url: str, browser_content: str) -> str: + def execute(self, url: str, browser_content: str) -> str: """Figure out next browser command to run. Args: diff --git a/langchain/chains/python.py b/langchain/chains/python.py index 32311daed91..74e598c24e4 100644 --- a/langchain/chains/python.py +++ b/langchain/chains/python.py @@ -41,7 +41,7 @@ class PythonChain(Chain, BaseModel): """ return [self.output_key] - def _run(self, inputs: Dict[str, str]) -> Dict[str, str]: + def _call(self, inputs: Dict[str, str]) -> Dict[str, str]: python_repl = PythonREPL() old_stdout = sys.stdout sys.stdout = mystdout = StringIO() @@ -49,20 +49,3 @@ class PythonChain(Chain, BaseModel): sys.stdout = old_stdout output = mystdout.getvalue() return {self.output_key: output} - - def run(self, code: str) -> str: - """Run code in python interpreter. - - Args: - code: Code snippet to execute, should print out the answer. - - Returns: - Answer from running the code and printing out the answer. - - Example: - - .. code-block:: python - - answer = python_chain.run("print(1+1)") - """ - return self({self.input_key: code})[self.output_key] diff --git a/langchain/chains/react/base.py b/langchain/chains/react/base.py index 2cd4dd25891..478630d6b42 100644 --- a/langchain/chains/react/base.py +++ b/langchain/chains/react/base.py @@ -72,9 +72,9 @@ class ReActChain(Chain, BaseModel): :meta private: """ - return ["full_logic", self.output_key] + return [self.output_key] - def _run(self, inputs: Dict[str, Any]) -> Dict[str, str]: + def _call(self, inputs: Dict[str, Any]) -> Dict[str, str]: question = inputs[self.input_key] llm_chain = LLMChain(llm=self.llm, prompt=PROMPT) chained_input = ChainedInput(f"{question}\nThought 1:", verbose=self.verbose) @@ -98,27 +98,10 @@ class ReActChain(Chain, BaseModel): raise ValueError("Cannot lookup without a successful search first") observation = document.lookup(directive) elif action == "Finish": - return {"full_logic": chained_input.input, self.output_key: directive} + return {self.output_key: directive} else: raise ValueError(f"Got unknown action directive: {action}") chained_input.add(f"\nObservation {i}: ") chained_input.add(observation, color="yellow") chained_input.add(f"\nThought {i + 1}:") i += 1 - - def run(self, question: str) -> str: - """Run ReAct framework. - - Args: - question: Question to be answered. - - Returns: - Final answer from thinking through the ReAct framework. - - Example: - .. code-block:: python - - question = "Were Scott Derrickson and Ed Wood of the same nationality?" - answer = react.run(question) - """ - return self({self.input_key: question})[self.output_key] diff --git a/langchain/chains/self_ask_with_search/base.py b/langchain/chains/self_ask_with_search/base.py index 26df99ee893..fe5ddb37c8e 100644 --- a/langchain/chains/self_ask_with_search/base.py +++ b/langchain/chains/self_ask_with_search/base.py @@ -114,7 +114,7 @@ class SelfAskWithSearchChain(Chain, BaseModel): """ return [self.output_key] - def _run(self, inputs: Dict[str, Any]) -> Dict[str, str]: + def _call(self, inputs: Dict[str, Any]) -> Dict[str, str]: chained_input = ChainedInput(inputs[self.input_key], verbose=self.verbose) chained_input.add("\nAre follow up questions needed here:") llm_chain = LLMChain(llm=self.llm, prompt=PROMPT) @@ -125,7 +125,7 @@ class SelfAskWithSearchChain(Chain, BaseModel): chained_input.add(ret_text, color="green") while followup in get_last_line(ret_text): question = extract_question(ret_text, followup) - external_answer = self.search_chain.search(question) + external_answer = self.search_chain.run(question) if external_answer is not None: chained_input.add(intermediate + " ") chained_input.add(external_answer + ".", color="yellow") @@ -147,19 +147,3 @@ class SelfAskWithSearchChain(Chain, BaseModel): chained_input.add(ret_text, color="green") return {self.output_key: ret_text} - - def run(self, question: str) -> str: - """Run self ask with search chain. - - Args: - question: Question to run self-ask-with-search with. - - Returns: - The final answer - - Example: - .. code-block:: python - - answer = selfask.run("What is the capital of Idaho?") - """ - return self({self.input_key: question})[self.output_key] diff --git a/langchain/chains/serpapi.py b/langchain/chains/serpapi.py index b8ea59198eb..dbac148b898 100644 --- a/langchain/chains/serpapi.py +++ b/langchain/chains/serpapi.py @@ -88,7 +88,7 @@ class SerpAPIChain(Chain, BaseModel): ) return values - def _run(self, inputs: Dict[str, Any]) -> Dict[str, str]: + def _call(self, inputs: Dict[str, Any]) -> Dict[str, str]: params = { "api_key": self.serpapi_api_key, "engine": "google", @@ -116,19 +116,3 @@ class SerpAPIChain(Chain, BaseModel): else: toret = None return {self.output_key: toret} - - def search(self, search_question: str) -> str: - """Run search query against SerpAPI. - - Args: - search_question: Question to run against the SerpAPI. - - Returns: - Answer from the search engine. - - Example: - .. code-block:: python - - answer = serpapi.search("What is the capital of Idaho?") - """ - return self({self.input_key: search_question})[self.output_key] diff --git a/langchain/chains/sql_database/base.py b/langchain/chains/sql_database/base.py index 47db1265c37..32bb1c9ce76 100644 --- a/langchain/chains/sql_database/base.py +++ b/langchain/chains/sql_database/base.py @@ -51,7 +51,7 @@ class SQLDatabaseChain(Chain, BaseModel): """ return [self.output_key] - def _run(self, inputs: Dict[str, str]) -> Dict[str, str]: + def _call(self, inputs: Dict[str, str]) -> Dict[str, str]: llm_chain = LLMChain(llm=self.llm, prompt=PROMPT) chained_input = ChainedInput( inputs[self.input_key] + "\nSQLQuery:", verbose=self.verbose @@ -72,19 +72,3 @@ class SQLDatabaseChain(Chain, BaseModel): final_result = llm_chain.predict(**llm_inputs) chained_input.add(final_result, color="green") return {self.output_key: final_result} - - def query(self, query: str) -> str: - """Run natural language query against a SQL database. - - Args: - query: natural language query to run against the SQL database - - Returns: - The final answer as derived from the SQL database. - - Example: - .. code-block:: python - - answer = db_chain.query("How many customers are there?") - """ - return self({self.input_key: query})[self.output_key] diff --git a/langchain/chains/vector_db_qa/base.py b/langchain/chains/vector_db_qa/base.py index 208d7f555f1..a87ca2e48d5 100644 --- a/langchain/chains/vector_db_qa/base.py +++ b/langchain/chains/vector_db_qa/base.py @@ -52,7 +52,7 @@ class VectorDBQA(Chain, BaseModel): """ return [self.output_key] - def _run(self, inputs: Dict[str, str]) -> Dict[str, str]: + def _call(self, inputs: Dict[str, str]) -> Dict[str, str]: question = inputs[self.input_key] llm_chain = LLMChain(llm=self.llm, prompt=prompt) docs = self.vectorstore.similarity_search(question) diff --git a/tests/integration_tests/chains/test_serpapi.py b/tests/integration_tests/chains/test_serpapi.py index 5f4aa048876..60cda1aa62d 100644 --- a/tests/integration_tests/chains/test_serpapi.py +++ b/tests/integration_tests/chains/test_serpapi.py @@ -5,5 +5,5 @@ from langchain.chains.serpapi import SerpAPIChain def test_call() -> None: """Test that call gives the correct answer.""" chain = SerpAPIChain() - output = chain.search("What was Obama's first name?") + output = chain.run("What was Obama's first name?") assert output == "Barack Hussein Obama II" diff --git a/tests/integration_tests/chains/test_sql_database.py b/tests/integration_tests/chains/test_sql_database.py index f874cc25893..8f6ab55bb4c 100644 --- a/tests/integration_tests/chains/test_sql_database.py +++ b/tests/integration_tests/chains/test_sql_database.py @@ -25,6 +25,6 @@ def test_sql_database_run() -> None: conn.execute(stmt) db = SQLDatabase(engine) db_chain = SQLDatabaseChain(llm=OpenAI(temperature=0), database=db) - output = db_chain.query("What company does Harrison work at?") + output = db_chain.run("What company does Harrison work at?") expected_output = " Harrison works at Foo." assert output == expected_output diff --git a/tests/unit_tests/chains/test_base.py b/tests/unit_tests/chains/test_base.py index 95ebb6f7ba5..2ab19c31b70 100644 --- a/tests/unit_tests/chains/test_base.py +++ b/tests/unit_tests/chains/test_base.py @@ -22,7 +22,7 @@ class FakeChain(Chain, BaseModel): """Output key of bar.""" return ["bar"] - def _run(self, inputs: Dict[str, str]) -> Dict[str, str]: + def _call(self, inputs: Dict[str, str]) -> Dict[str, str]: if self.be_correct: return {"bar": "baz"} else: diff --git a/tests/unit_tests/chains/test_natbot.py b/tests/unit_tests/chains/test_natbot.py index 622237ae312..bf4223b2917 100644 --- a/tests/unit_tests/chains/test_natbot.py +++ b/tests/unit_tests/chains/test_natbot.py @@ -26,7 +26,7 @@ def test_proper_inputs() -> None: nat_bot_chain = NatBotChain(llm=FakeLLM(), objective="testing") url = "foo" * 10000 browser_content = "foo" * 10000 - output = nat_bot_chain.run(url, browser_content) + output = nat_bot_chain.execute(url, browser_content) assert output == "bar" @@ -39,5 +39,5 @@ def test_variable_key_naming() -> None: input_browser_content_key="b", output_key="c", ) - output = nat_bot_chain.run("foo", "foo") + output = nat_bot_chain.execute("foo", "foo") assert output == "bar" diff --git a/tests/unit_tests/chains/test_react.py b/tests/unit_tests/chains/test_react.py index 4490be08b0d..f7be9c54e76 100644 --- a/tests/unit_tests/chains/test_react.py +++ b/tests/unit_tests/chains/test_react.py @@ -92,18 +92,6 @@ def test_react_chain() -> None: inputs = {"question": "when was langchain made"} output = react_chain(inputs) assert output["answer"] == "2022" - expected_full_output = ( - "when was langchain made\n" - "Thought 1:I should probably search\n" - "Action 1: Search[langchain]\n" - "Observation 1: This is a page about LangChain.\n" - "Thought 2:I should probably lookup\n" - "Action 2: Lookup[made]\n" - "Observation 2: (Result 1/1) Made in 2022.\n" - "Thought 3:Ah okay now I know the answer\n" - "Action 3: Finish[2022]" - ) - assert output["full_logic"] == expected_full_output def test_react_chain_bad_action() -> None: