From 2bef195a1f4593fbfbab6ba3cdad295134d6895b Mon Sep 17 00:00:00 2001 From: Harrison Chase Date: Sun, 4 Dec 2022 08:45:34 -0800 Subject: [PATCH 1/5] stash --- docs/examples/agents/react.ipynb | 29 ++++++++++++++++++-- langchain/agents/agent.py | 29 +++++++------------- langchain/agents/input.py | 40 +++++++++++++++++++++++++++ langchain/input.py | 22 --------------- langchain/logger.py | 46 ++++++++++++++++++++++++++++++++ langchain/schema.py | 11 ++++++++ tests/unit_tests/test_input.py | 3 ++- 7 files changed, 136 insertions(+), 44 deletions(-) create mode 100644 langchain/agents/input.py create mode 100644 langchain/logger.py create mode 100644 langchain/schema.py diff --git a/docs/examples/agents/react.ipynb b/docs/examples/agents/react.ipynb index aef1239030f7e..7db37ddae7282 100644 --- a/docs/examples/agents/react.ipynb +++ b/docs/examples/agents/react.ipynb @@ -38,7 +38,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "id": "8078c8f1", "metadata": {}, "outputs": [ @@ -46,9 +46,34 @@ "name": "stdout", "output_type": "stream", "text": [ + "\n", + "\n", + "\u001b[1m> Entering new ReActDocstoreAgent chain...\u001b[0m\n", "Author David Chanoff has collaborated with a U.S. Navy admiral who served as the ambassador to the United Kingdom under which President?\n", - "Thought 1:" + "Thought 1:\u001b[32;1m\u001b[1;3m I need to search David Chanoff and the U.S. Navy admiral, find the ambassador to the United Kingdom, then find the President they served under.\n", + "Action 1: Search[David Chanoff]\u001b[0m\n", + "Observation 0: \u001b[36;1m\u001b[1;3mDavid Chanoff is a noted author of non-fiction work. His work has typically involved collaborations with the principal protagonist of the work concerned. His collaborators have included; Augustus A. White, Joycelyn Elders, Đoàn Văn Toại, William J. Crowe, Ariel Sharon, Kenneth Good and Felix Zandman. He has also written about a wide range of subjects including literary history, education and foreign for The Washington Post, The New Republic and The New York Times Magazine. He has published more than twelve books.\u001b[0m\n", + "Thought 1:\u001b[32;1m\u001b[1;3m David Chanoff has collaborated with many people, so I need to search the U.S. Navy admiral specifically.\n", + "Action 2: Search[U.S. Navy admiral]\u001b[0m\n", + "Observation 0: \u001b[36;1m\u001b[1;3mAdmiral of the Navy was the highest-possible rank in the United States Navy, prior to the creation of fleet admiral in 1944. The rank is considered to be at least equivalent to that of a five-star admiral, with Admiral George Dewey being the only officer to be appointed to the rank.\u001b[0m\n", + "Thought 1:\u001b[32;1m\u001b[1;3m I need to search the U.S. Navy admiral who served as the ambassador to the United Kingdom.\n", + "Action 3: Search[U.S. Navy admiral ambassador to the United Kingdom]\n", + "Observation 0: Admiral William J. Crowe Jr. was the United States Ambassador to the United Kingdom from 1994 to 1997. He served as Chairman of the Joint Chiefs of Staff from 1985 to 1989.\n", + "Thought 1: Admiral William J. Crowe Jr. served as the United States Ambassador to the United Kingdom from 1994 to 1997. So the President they served under is Bill Clinton.\n", + "Action 4: Finish[Bill Clinton]\n", + "Action 3: Finish[Bill Clinton]\u001b[0m\n", + "\u001b[1m> Finished ReActDocstoreAgent chain.\u001b[0m\n" ] + }, + { + "data": { + "text/plain": [ + "'Bill Clinton'" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ diff --git a/langchain/agents/agent.py b/langchain/agents/agent.py index 80ee3ab1dc471..e2c2135b23018 100644 --- a/langchain/agents/agent.py +++ b/langchain/agents/agent.py @@ -2,24 +2,19 @@ from __future__ import annotations from abc import ABC, abstractmethod -from typing import Any, ClassVar, Dict, List, NamedTuple, Optional, Tuple +from typing import Any, ClassVar, Dict, List, Optional, Tuple from pydantic import BaseModel from langchain.agents.tools import Tool from langchain.chains.base import Chain from langchain.chains.llm import LLMChain -from langchain.input import ChainedInput, get_color_mapping +from langchain.input import get_color_mapping +from langchain.agents.input import ChainedInput from langchain.llms.base import LLM from langchain.prompts.base import BasePromptTemplate - - -class Action(NamedTuple): - """Action to take.""" - - tool: str - tool_input: str - log: str +from langchain.schema import AgentAction +from langchain.logger import logger class Agent(Chain, BaseModel, ABC): @@ -99,7 +94,7 @@ def from_llm_and_tools(cls, llm: LLM, tools: List[Tool], **kwargs: Any) -> Agent llm_chain = LLMChain(llm=llm, prompt=cls.create_prompt(tools)) return cls(llm_chain=llm_chain, tools=tools, **kwargs) - def get_action(self, text: str) -> Action: + def get_action(self, text: str) -> AgentAction: """Given input, decided what to do. Args: @@ -119,7 +114,7 @@ def get_action(self, text: str) -> Action: full_output += output parsed_output = self._extract_tool_and_input(full_output) tool, tool_input = parsed_output - return Action(tool, tool_input, full_output) + return AgentAction(tool, tool_input, full_output) def _call(self, inputs: Dict[str, str]) -> Dict[str, str]: """Run text through and get agent response.""" @@ -135,7 +130,7 @@ def _call(self, inputs: Dict[str, str]) -> Dict[str, str]: # prompts the LLM to take an action. starter_string = text + self.starter_string + self.llm_prefix # We use the ChainedInput class to iteratively add to the input over time. - chained_input = ChainedInput(starter_string, verbose=self.verbose) + chained_input = ChainedInput(starter_string, self.observation_prefix, self.llm_prefix, verbose=self.verbose) # We construct a mapping from each tool to a color, used for logging. color_mapping = get_color_mapping( [tool.name for tool in self.tools], excluded_colors=["green"] @@ -145,7 +140,7 @@ def _call(self, inputs: Dict[str, str]) -> Dict[str, str]: # Call the LLM to see what to do. output = self.get_action(chained_input.input) # Add the log to the Chained Input. - chained_input.add(output.log, color="green") + chained_input.add_action(output, color="green") # If the tool chosen is the finishing tool, then we end and return. if output.tool == self.finish_tool_name: return {self.output_key: output.tool_input} @@ -154,8 +149,4 @@ def _call(self, inputs: Dict[str, str]) -> Dict[str, str]: # We then call the tool on the tool input to get an observation observation = chain(output.tool_input) # We then log the observation - chained_input.add(f"\n{self.observation_prefix}") - chained_input.add(observation, color=color_mapping[output.tool]) - # We then add the LLM prefix into the prompt to get the LLM to start - # thinking, and start the loop all over. - chained_input.add(f"\n{self.llm_prefix}") + chained_input.add_observation(observation, color=color_mapping[output.tool]) diff --git a/langchain/agents/input.py b/langchain/agents/input.py new file mode 100644 index 0000000000000..fec1dbe4b15ae --- /dev/null +++ b/langchain/agents/input.py @@ -0,0 +1,40 @@ +"""Input manager for agents.""" +from typing import Optional + +from langchain.schema import AgentAction +from langchain.logger import logger + + +class ChainedInput: + """Class for working with input that is the result of chains.""" + + def __init__(self, text: str, observation_prefix: str, llm_prefix: str, verbose: bool = False): + """Initialize with verbose flag and initial text.""" + self._verbose = verbose + if self._verbose: + logger.log_agent_start(text) + self._input = text + self._observation_prefix = observation_prefix + self._llm_prefix = llm_prefix + + def add_action(self, action: AgentAction, color: Optional[str] = None) -> None: + """Add text to input, print if in verbose mode.""" + if self._verbose: + logger.log_agent_action(action, color=color) + self._input += action.log + + def add_observation(self, observation: str, color: Optional[str]) -> None: + """Add observation to input, print if in verbose mode.""" + if self._verbose: + logger.log_agent_observation( + observation, + color=color, + observation_prefix=self._observation_prefix, + llm_prefix=self._llm_prefix, + ) + self._input += f"\n{self._observation_prefix}{observation}\n{self._llm_prefix}" + + @property + def input(self) -> str: + """Return the accumulated input.""" + return self._input diff --git a/langchain/input.py b/langchain/input.py index 782cd41a8bff1..680685fff518e 100644 --- a/langchain/input.py +++ b/langchain/input.py @@ -27,25 +27,3 @@ def print_text(text: str, color: Optional[str] = None, end: str = "") -> None: else: color_str = _TEXT_COLOR_MAPPING[color] print(f"\u001b[{color_str}m\033[1;3m{text}\u001b[0m", end=end) - - -class ChainedInput: - """Class for working with input that is the result of chains.""" - - def __init__(self, text: str, verbose: bool = False): - """Initialize with verbose flag and initial text.""" - self._verbose = verbose - if self._verbose: - print_text(text, color=None) - self._input = text - - def add(self, text: str, color: Optional[str] = None) -> None: - """Add text to input, print if in verbose mode.""" - if self._verbose: - print_text(text, color=color) - self._input += text - - @property - def input(self) -> str: - """Return the accumulated input.""" - return self._input diff --git a/langchain/logger.py b/langchain/logger.py new file mode 100644 index 0000000000000..546cda29ee91b --- /dev/null +++ b/langchain/logger.py @@ -0,0 +1,46 @@ +from langchain.schema import AgentAction +from typing import Optional, Any +from langchain.input import print_text +import logging +logging.basicConfig + + +class BaseLogger: + + def log_agent_start(self, text: str, **kwargs: Any): + pass + + def log_agent_end(self, text: str, **kwargs: Any): + pass + + def log_agent_action(self, action: AgentAction, **kwargs: Any): + pass + + def log_agent_observation(self, observation: str, **kwargs: Any): + pass + + +class StOutLogger(BaseLogger): + def log_agent_start(self, text: str, **kwargs: Any): + print_text(text) + + def log_agent_end(self, text: str, **kwargs: Any): + pass + + def log_agent_action(self, action: AgentAction, color: Optional[str] = None, **kwargs: Any): + print_text(action.log, color=color) + + def log_agent_observation( + self, + observation: str, + color: Optional[str] = None, + observation_prefix: Optional[str] = None, + llm_prefix: Optional[str] = None, + **kwargs: Any): + print_text(f"\n{observation_prefix}") + print_text(observation, color=color) + print_text(f"\n{llm_prefix}") + + + +logger = StOutLogger() \ No newline at end of file diff --git a/langchain/schema.py b/langchain/schema.py new file mode 100644 index 0000000000000..389839f489c5c --- /dev/null +++ b/langchain/schema.py @@ -0,0 +1,11 @@ +from __future__ import annotations + +from typing import NamedTuple + + +class AgentAction(NamedTuple): + """Agent's action to take.""" + + tool: str + tool_input: str + log: str diff --git a/tests/unit_tests/test_input.py b/tests/unit_tests/test_input.py index 43dd3b080b889..dafc495520ac7 100644 --- a/tests/unit_tests/test_input.py +++ b/tests/unit_tests/test_input.py @@ -3,7 +3,8 @@ import sys from io import StringIO -from langchain.input import ChainedInput, get_color_mapping +from langchain.input import get_color_mapping +from langchain.agents.input import ChainedInput def test_chained_input_not_verbose() -> None: From c2580cf401705682a450eb92ff453d865114a3de Mon Sep 17 00:00:00 2001 From: Harrison Chase Date: Sun, 4 Dec 2022 16:35:13 -0800 Subject: [PATCH 2/5] stash --- docs/examples/agents/react.ipynb | 22 ++++++++++++---------- langchain/agents/agent.py | 4 ++-- langchain/agents/input.py | 12 +++++------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/docs/examples/agents/react.ipynb b/docs/examples/agents/react.ipynb index 7db37ddae7282..71ae58f53efc7 100644 --- a/docs/examples/agents/react.ipynb +++ b/docs/examples/agents/react.ipynb @@ -52,23 +52,25 @@ "Author David Chanoff has collaborated with a U.S. Navy admiral who served as the ambassador to the United Kingdom under which President?\n", "Thought 1:\u001b[32;1m\u001b[1;3m I need to search David Chanoff and the U.S. Navy admiral, find the ambassador to the United Kingdom, then find the President they served under.\n", "Action 1: Search[David Chanoff]\u001b[0m\n", - "Observation 0: \u001b[36;1m\u001b[1;3mDavid Chanoff is a noted author of non-fiction work. His work has typically involved collaborations with the principal protagonist of the work concerned. His collaborators have included; Augustus A. White, Joycelyn Elders, Đoàn Văn Toại, William J. Crowe, Ariel Sharon, Kenneth Good and Felix Zandman. He has also written about a wide range of subjects including literary history, education and foreign for The Washington Post, The New Republic and The New York Times Magazine. He has published more than twelve books.\u001b[0m\n", - "Thought 1:\u001b[32;1m\u001b[1;3m David Chanoff has collaborated with many people, so I need to search the U.S. Navy admiral specifically.\n", + "Observation 1: \u001b[36;1m\u001b[1;3mDavid Chanoff is a noted author of non-fiction work. His work has typically involved collaborations with the principal protagonist of the work concerned. His collaborators have included; Augustus A. White, Joycelyn Elders, Đoàn Văn Toại, William J. Crowe, Ariel Sharon, Kenneth Good and Felix Zandman. He has also written about a wide range of subjects including literary history, education and foreign for The Washington Post, The New Republic and The New York Times Magazine. He has published more than twelve books.\u001b[0m\n", + "Thought 2:\u001b[32;1m\u001b[1;3m David Chanoff has collaborated with a U.S. Navy admiral. I need to search the U.S. Navy admiral and find the ambassador to the United Kingdom.\n", "Action 2: Search[U.S. Navy admiral]\u001b[0m\n", - "Observation 0: \u001b[36;1m\u001b[1;3mAdmiral of the Navy was the highest-possible rank in the United States Navy, prior to the creation of fleet admiral in 1944. The rank is considered to be at least equivalent to that of a five-star admiral, with Admiral George Dewey being the only officer to be appointed to the rank.\u001b[0m\n", - "Thought 1:\u001b[32;1m\u001b[1;3m I need to search the U.S. Navy admiral who served as the ambassador to the United Kingdom.\n", - "Action 3: Search[U.S. Navy admiral ambassador to the United Kingdom]\n", - "Observation 0: Admiral William J. Crowe Jr. was the United States Ambassador to the United Kingdom from 1994 to 1997. He served as Chairman of the Joint Chiefs of Staff from 1985 to 1989.\n", - "Thought 1: Admiral William J. Crowe Jr. served as the United States Ambassador to the United Kingdom from 1994 to 1997. So the President they served under is Bill Clinton.\n", - "Action 4: Finish[Bill Clinton]\n", - "Action 3: Finish[Bill Clinton]\u001b[0m\n", + "Observation 2: \u001b[36;1m\u001b[1;3mAdmiral of the Navy was the highest-possible rank in the United States Navy, prior to the creation of fleet admiral in 1944. The rank is considered to be at least equivalent to that of a five-star admiral, with Admiral George Dewey being the only officer to be appointed to the rank.\u001b[0m\n", + "Thought 3:\u001b[32;1m\u001b[1;3m The U.S. Navy admiral is Admiral George Dewey. I need to search Admiral George Dewey and find the ambassador to the United Kingdom.\n", + "Action 3: Search[Admiral George Dewey]\u001b[0m\n", + "Observation 3: \u001b[36;1m\u001b[1;3mGeorge Dewey (December 26, 1837 – January 16, 1917) was Admiral of the Navy, the only person in United States history to have attained that rank. He is best known for his victory at the Battle of Manila Bay during the Spanish–American War, with the loss of only a single crewman on the American side.\n", + "Dewey was born in Montpelier, Vermont. At age 15, Dewey's father enrolled him at Norwich University in Northfield, Vermont. Two years later Norwich expelled him for drunkenness and herding sheep into the barracks. Summarily, he entered the United States Naval Academy in 1854. He graduated from the academy in 1858 and was assigned as the executive lieutenant of the USS Mississippi at the beginning of the Civil War. He participated in the capture of New Orleans and the Siege of Port Hudson, helping the Union take control of the Mississippi River. By the end of the war, Dewey reached the rank of lieutenant commander.\n", + "After the Civil War, Dewey undertook a variety of assignments, serving on multiple ships (including the USS Constitution) and as an instructor at the Naval Academy. He also served on the United States Lighthouse Board and the Board of Inspection and Survey. He was promoted to commodore in 1896 and assigned to the Asiatic Squadron the following year. After that appointment, he began preparations for a potential war with Spain, which broke out in April 1898. Immediately after the beginning of the war, Dewey led an attack on Manila Bay, sinking the entire Spanish Pacific fleet while suffering only minor casualties. After the battle, his fleet assisted in the capture of Manila. Dewey's victory at Manila Bay was widely lauded in the United States, and he was promoted to Admiral of the Navy in 1903.\n", + "Dewey explored a run for the 1900 Democratic presidential nomination, but he withdrew from the race and endorsed President William McKinley. He served on the General Board of the United States Navy, an important policy-making body, from 1900 until his death in 1917.\u001b[0m\n", + "Thought 4:\u001b[32;1m\u001b[1;3m Admiral George Dewey served as the ambassador to the United Kingdom under President William McKinley.\n", + "Action 4: Finish[William McKinley]\u001b[0m\n", "\u001b[1m> Finished ReActDocstoreAgent chain.\u001b[0m\n" ] }, { "data": { "text/plain": [ - "'Bill Clinton'" + "'William McKinley'" ] }, "execution_count": 2, diff --git a/langchain/agents/agent.py b/langchain/agents/agent.py index e2c2135b23018..3ede815d7b6d4 100644 --- a/langchain/agents/agent.py +++ b/langchain/agents/agent.py @@ -130,7 +130,7 @@ def _call(self, inputs: Dict[str, str]) -> Dict[str, str]: # prompts the LLM to take an action. starter_string = text + self.starter_string + self.llm_prefix # We use the ChainedInput class to iteratively add to the input over time. - chained_input = ChainedInput(starter_string, self.observation_prefix, self.llm_prefix, verbose=self.verbose) + chained_input = ChainedInput(starter_string, verbose=self.verbose) # We construct a mapping from each tool to a color, used for logging. color_mapping = get_color_mapping( [tool.name for tool in self.tools], excluded_colors=["green"] @@ -149,4 +149,4 @@ def _call(self, inputs: Dict[str, str]) -> Dict[str, str]: # We then call the tool on the tool input to get an observation observation = chain(output.tool_input) # We then log the observation - chained_input.add_observation(observation, color=color_mapping[output.tool]) + chained_input.add_observation(observation, self.observation_prefix, self.llm_prefix, color=color_mapping[output.tool]) diff --git a/langchain/agents/input.py b/langchain/agents/input.py index fec1dbe4b15ae..999bad7135f05 100644 --- a/langchain/agents/input.py +++ b/langchain/agents/input.py @@ -8,14 +8,12 @@ class ChainedInput: """Class for working with input that is the result of chains.""" - def __init__(self, text: str, observation_prefix: str, llm_prefix: str, verbose: bool = False): + def __init__(self, text: str, verbose: bool = False): """Initialize with verbose flag and initial text.""" self._verbose = verbose if self._verbose: logger.log_agent_start(text) self._input = text - self._observation_prefix = observation_prefix - self._llm_prefix = llm_prefix def add_action(self, action: AgentAction, color: Optional[str] = None) -> None: """Add text to input, print if in verbose mode.""" @@ -23,16 +21,16 @@ def add_action(self, action: AgentAction, color: Optional[str] = None) -> None: logger.log_agent_action(action, color=color) self._input += action.log - def add_observation(self, observation: str, color: Optional[str]) -> None: + def add_observation(self, observation: str, observation_prefix: str, llm_prefix: str, color: Optional[str]) -> None: """Add observation to input, print if in verbose mode.""" if self._verbose: logger.log_agent_observation( observation, color=color, - observation_prefix=self._observation_prefix, - llm_prefix=self._llm_prefix, + observation_prefix=observation_prefix, + llm_prefix=llm_prefix, ) - self._input += f"\n{self._observation_prefix}{observation}\n{self._llm_prefix}" + self._input += f"\n{observation_prefix}{observation}\n{llm_prefix}" @property def input(self) -> str: From bf8bed493ff75a5007c42cfc9f3b5009db7bbd6c Mon Sep 17 00:00:00 2001 From: Harrison Chase Date: Sun, 4 Dec 2022 19:31:57 -0800 Subject: [PATCH 3/5] wip logging --- docs/examples/agents/react.ipynb | 31 ++++++++++------------- langchain/__init__.py | 3 +++ langchain/agents/agent.py | 10 +++++--- langchain/agents/input.py | 16 ++++++++---- langchain/chains/llm.py | 7 +++--- langchain/logger.py | 42 ++++++++++++++++++++------------ tests/unit_tests/test_input.py | 2 +- 7 files changed, 65 insertions(+), 46 deletions(-) diff --git a/docs/examples/agents/react.ipynb b/docs/examples/agents/react.ipynb index 71ae58f53efc7..4af4c6727f183 100644 --- a/docs/examples/agents/react.ipynb +++ b/docs/examples/agents/react.ipynb @@ -12,7 +12,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 6, "id": "4e272b47", "metadata": {}, "outputs": [], @@ -32,13 +32,13 @@ " )\n", "]\n", "\n", - "llm = OpenAI(temperature=0)\n", + "llm = OpenAI(temperature=0, model_name=\"text-davinci-002\")\n", "react = initialize_agent(tools, llm, agent=\"react-docstore\", verbose=True)" ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 7, "id": "8078c8f1", "metadata": {}, "outputs": [ @@ -50,30 +50,25 @@ "\n", "\u001b[1m> Entering new ReActDocstoreAgent chain...\u001b[0m\n", "Author David Chanoff has collaborated with a U.S. Navy admiral who served as the ambassador to the United Kingdom under which President?\n", - "Thought 1:\u001b[32;1m\u001b[1;3m I need to search David Chanoff and the U.S. Navy admiral, find the ambassador to the United Kingdom, then find the President they served under.\n", + "Thought 1:\u001b[32;1m\u001b[1;3m I need to search David Chanoff and find the U.S. Navy admiral he collaborated\n", + "with.\n", "Action 1: Search[David Chanoff]\u001b[0m\n", "Observation 1: \u001b[36;1m\u001b[1;3mDavid Chanoff is a noted author of non-fiction work. His work has typically involved collaborations with the principal protagonist of the work concerned. His collaborators have included; Augustus A. White, Joycelyn Elders, Đoàn Văn Toại, William J. Crowe, Ariel Sharon, Kenneth Good and Felix Zandman. He has also written about a wide range of subjects including literary history, education and foreign for The Washington Post, The New Republic and The New York Times Magazine. He has published more than twelve books.\u001b[0m\n", - "Thought 2:\u001b[32;1m\u001b[1;3m David Chanoff has collaborated with a U.S. Navy admiral. I need to search the U.S. Navy admiral and find the ambassador to the United Kingdom.\n", - "Action 2: Search[U.S. Navy admiral]\u001b[0m\n", - "Observation 2: \u001b[36;1m\u001b[1;3mAdmiral of the Navy was the highest-possible rank in the United States Navy, prior to the creation of fleet admiral in 1944. The rank is considered to be at least equivalent to that of a five-star admiral, with Admiral George Dewey being the only officer to be appointed to the rank.\u001b[0m\n", - "Thought 3:\u001b[32;1m\u001b[1;3m The U.S. Navy admiral is Admiral George Dewey. I need to search Admiral George Dewey and find the ambassador to the United Kingdom.\n", - "Action 3: Search[Admiral George Dewey]\u001b[0m\n", - "Observation 3: \u001b[36;1m\u001b[1;3mGeorge Dewey (December 26, 1837 – January 16, 1917) was Admiral of the Navy, the only person in United States history to have attained that rank. He is best known for his victory at the Battle of Manila Bay during the Spanish–American War, with the loss of only a single crewman on the American side.\n", - "Dewey was born in Montpelier, Vermont. At age 15, Dewey's father enrolled him at Norwich University in Northfield, Vermont. Two years later Norwich expelled him for drunkenness and herding sheep into the barracks. Summarily, he entered the United States Naval Academy in 1854. He graduated from the academy in 1858 and was assigned as the executive lieutenant of the USS Mississippi at the beginning of the Civil War. He participated in the capture of New Orleans and the Siege of Port Hudson, helping the Union take control of the Mississippi River. By the end of the war, Dewey reached the rank of lieutenant commander.\n", - "After the Civil War, Dewey undertook a variety of assignments, serving on multiple ships (including the USS Constitution) and as an instructor at the Naval Academy. He also served on the United States Lighthouse Board and the Board of Inspection and Survey. He was promoted to commodore in 1896 and assigned to the Asiatic Squadron the following year. After that appointment, he began preparations for a potential war with Spain, which broke out in April 1898. Immediately after the beginning of the war, Dewey led an attack on Manila Bay, sinking the entire Spanish Pacific fleet while suffering only minor casualties. After the battle, his fleet assisted in the capture of Manila. Dewey's victory at Manila Bay was widely lauded in the United States, and he was promoted to Admiral of the Navy in 1903.\n", - "Dewey explored a run for the 1900 Democratic presidential nomination, but he withdrew from the race and endorsed President William McKinley. He served on the General Board of the United States Navy, an important policy-making body, from 1900 until his death in 1917.\u001b[0m\n", - "Thought 4:\u001b[32;1m\u001b[1;3m Admiral George Dewey served as the ambassador to the United Kingdom under President William McKinley.\n", - "Action 4: Finish[William McKinley]\u001b[0m\n", + "Thought 2:\u001b[32;1m\u001b[1;3m The U.S. Navy admiral David Chanoff collaborated with is William J. Crowe.\n", + "Action 2: Search[William J. Crowe]\u001b[0m\n", + "Observation 2: \u001b[36;1m\u001b[1;3mWilliam James Crowe Jr. (January 2, 1925 – October 18, 2007) was a United States Navy admiral and diplomat who served as the 11th chairman of the Joint Chiefs of Staff under Presidents Ronald Reagan and George H. W. Bush, and as the ambassador to the United Kingdom and Chair of the Intelligence Oversight Board under President Bill Clinton.\u001b[0m\n", + "Thought 3:\u001b[32;1m\u001b[1;3m William J. Crowe served as the ambassador to the United Kingdom under President Bill Clinton.\n", + "Action 3: Finish[Bill Clinton]\u001b[0m\n", "\u001b[1m> Finished ReActDocstoreAgent chain.\u001b[0m\n" ] }, { "data": { "text/plain": [ - "'William McKinley'" + "'Bill Clinton'" ] }, - "execution_count": 2, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } @@ -108,7 +103,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.6" + "version": "3.10.8" } }, "nbformat": 4, diff --git a/langchain/__init__.py b/langchain/__init__.py index 32bbba1773755..328d76fd2a389 100644 --- a/langchain/__init__.py +++ b/langchain/__init__.py @@ -18,6 +18,7 @@ ) from langchain.docstore import InMemoryDocstore, Wikipedia from langchain.llms import Cohere, HuggingFaceHub, OpenAI +from langchain.logger import BaseLogger from langchain.prompts import ( BasePromptTemplate, FewShotPromptTemplate, @@ -28,6 +29,8 @@ from langchain.sql_database import SQLDatabase from langchain.vectorstores import FAISS, ElasticVectorSearch +logger = BaseLogger() + __all__ = [ "LLMChain", "LLMMathChain", diff --git a/langchain/agents/agent.py b/langchain/agents/agent.py index 3ede815d7b6d4..99ace7a0d09f7 100644 --- a/langchain/agents/agent.py +++ b/langchain/agents/agent.py @@ -6,15 +6,14 @@ from pydantic import BaseModel +from langchain.agents.input import ChainedInput from langchain.agents.tools import Tool from langchain.chains.base import Chain from langchain.chains.llm import LLMChain from langchain.input import get_color_mapping -from langchain.agents.input import ChainedInput from langchain.llms.base import LLM from langchain.prompts.base import BasePromptTemplate from langchain.schema import AgentAction -from langchain.logger import logger class Agent(Chain, BaseModel, ABC): @@ -149,4 +148,9 @@ def _call(self, inputs: Dict[str, str]) -> Dict[str, str]: # We then call the tool on the tool input to get an observation observation = chain(output.tool_input) # We then log the observation - chained_input.add_observation(observation, self.observation_prefix, self.llm_prefix, color=color_mapping[output.tool]) + chained_input.add_observation( + observation, + self.observation_prefix, + self.llm_prefix, + color=color_mapping[output.tool], + ) diff --git a/langchain/agents/input.py b/langchain/agents/input.py index 999bad7135f05..6659ad091c063 100644 --- a/langchain/agents/input.py +++ b/langchain/agents/input.py @@ -1,8 +1,8 @@ """Input manager for agents.""" from typing import Optional +import langchain from langchain.schema import AgentAction -from langchain.logger import logger class ChainedInput: @@ -12,19 +12,25 @@ def __init__(self, text: str, verbose: bool = False): """Initialize with verbose flag and initial text.""" self._verbose = verbose if self._verbose: - logger.log_agent_start(text) + langchain.logger.log_agent_start(text) self._input = text def add_action(self, action: AgentAction, color: Optional[str] = None) -> None: """Add text to input, print if in verbose mode.""" if self._verbose: - logger.log_agent_action(action, color=color) + langchain.logger.log_agent_action(action, color=color) self._input += action.log - def add_observation(self, observation: str, observation_prefix: str, llm_prefix: str, color: Optional[str]) -> None: + def add_observation( + self, + observation: str, + observation_prefix: str, + llm_prefix: str, + color: Optional[str], + ) -> None: """Add observation to input, print if in verbose mode.""" if self._verbose: - logger.log_agent_observation( + langchain.logger.log_agent_observation( observation, color=color, observation_prefix=observation_prefix, diff --git a/langchain/chains/llm.py b/langchain/chains/llm.py index 544628524c812..a1575ed450fdf 100644 --- a/langchain/chains/llm.py +++ b/langchain/chains/llm.py @@ -3,8 +3,8 @@ from pydantic import BaseModel, Extra +import langchain from langchain.chains.base import Chain -from langchain.input import print_text from langchain.llms.base import LLM from langchain.prompts.base import BasePromptTemplate @@ -55,12 +55,13 @@ 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) if self.verbose: - print("Prompt after formatting:") - print_text(prompt, color="green", end="\n") + langchain.logger.log_llm_inputs(selected_inputs, prompt) kwargs = {} if "stop" in inputs: kwargs["stop"] = inputs["stop"] response = self.llm(prompt, **kwargs) + if self.verbose: + langchain.logger.log_llm_response(response) return {self.output_key: response} def predict(self, **kwargs: Any) -> str: diff --git a/langchain/logger.py b/langchain/logger.py index 546cda29ee91b..0b9a83383ce25 100644 --- a/langchain/logger.py +++ b/langchain/logger.py @@ -1,12 +1,10 @@ -from langchain.schema import AgentAction -from typing import Optional, Any +from typing import Any, Optional + from langchain.input import print_text -import logging -logging.basicConfig +from langchain.schema import AgentAction class BaseLogger: - def log_agent_start(self, text: str, **kwargs: Any): pass @@ -19,6 +17,12 @@ def log_agent_action(self, action: AgentAction, **kwargs: Any): def log_agent_observation(self, observation: str, **kwargs: Any): pass + def log_llm_inputs(self, inputs: dict, prompt: str, **kwargs): + pass + + def log_llm_response(self, output: str, **kwargs): + pass + class StOutLogger(BaseLogger): def log_agent_start(self, text: str, **kwargs: Any): @@ -27,20 +31,26 @@ def log_agent_start(self, text: str, **kwargs: Any): def log_agent_end(self, text: str, **kwargs: Any): pass - def log_agent_action(self, action: AgentAction, color: Optional[str] = None, **kwargs: Any): + def log_agent_action( + self, action: AgentAction, color: Optional[str] = None, **kwargs: Any + ): print_text(action.log, color=color) + def log_llm_inputs(self, inputs: dict, prompt: str, **kwargs): + print("Prompt after formatting:") + print_text(prompt, color="green", end="\n") + + def log_llm_response(self, output: str, **kwargs): + pass + def log_agent_observation( - self, - observation: str, - color: Optional[str] = None, - observation_prefix: Optional[str] = None, - llm_prefix: Optional[str] = None, - **kwargs: Any): + self, + observation: str, + color: Optional[str] = None, + observation_prefix: Optional[str] = None, + llm_prefix: Optional[str] = None, + **kwargs: Any, + ): print_text(f"\n{observation_prefix}") print_text(observation, color=color) print_text(f"\n{llm_prefix}") - - - -logger = StOutLogger() \ No newline at end of file diff --git a/tests/unit_tests/test_input.py b/tests/unit_tests/test_input.py index dafc495520ac7..fb85593dfb358 100644 --- a/tests/unit_tests/test_input.py +++ b/tests/unit_tests/test_input.py @@ -3,8 +3,8 @@ import sys from io import StringIO -from langchain.input import get_color_mapping from langchain.agents.input import ChainedInput +from langchain.input import get_color_mapping def test_chained_input_not_verbose() -> None: From ec842b7e7bdb9574093dcd3707fada63b1a061d4 Mon Sep 17 00:00:00 2001 From: Harrison Chase Date: Sun, 4 Dec 2022 20:29:19 -0800 Subject: [PATCH 4/5] fix logging in api chain --- langchain/chains/api/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/langchain/chains/api/base.py b/langchain/chains/api/base.py index b73c96bb6cf2f..807e86354d587 100644 --- a/langchain/chains/api/base.py +++ b/langchain/chains/api/base.py @@ -80,7 +80,7 @@ def _call(self, inputs: Dict[str, str]) -> Dict[str, str]: print_text(api_url, color="green", end="\n") api_response = self.requests_wrapper.run(api_url) if self.verbose: - print_text(api_url, color="yellow", end="\n") + print_text(api_response, color="yellow", end="\n") answer = self.api_answer_chain.predict( question=question, api_docs=self.api_docs, From ec65ca00c105e39faa2d7b0272203a83aeb4e6de Mon Sep 17 00:00:00 2001 From: Harrison Chase Date: Sun, 4 Dec 2022 20:34:53 -0800 Subject: [PATCH 5/5] cr --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index c690a8080ac8a..5083153d21753 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langchain" -version = "0.0.28" +version = "0.0.29" description = "Building applications with LLMs through composability" authors = [] license = "MIT" @@ -21,7 +21,6 @@ manifest-ml = {version = "^0.0.1", optional = true} spacy = {version = "^3", optional = true} nltk = {version = "^3", optional = true} transformers = {version = "^4", optional = true} -types-toml = "^0.10.8.1" [tool.poetry.group.test.dependencies] pytest = "^7.2.0" @@ -37,6 +36,7 @@ flake8 = "^6.0.0" mypy = "^0.991" types-pyyaml = "^6.0.12.2" types-requests = "^2.28.11.5" +types-toml = "^0.10.8.1" [tool.poetry.group.dev] optional = true