Compare commits

...

8 Commits

Author SHA1 Message Date
Harrison Chase ec65ca00c1 cr 1 year ago
Harrison Chase 64ea17bd21 Merge branch 'master' into harrison/fix_logging_api 1 year ago
Harrison Chase ec842b7e7b fix logging in api chain 1 year ago
Harrison Chase bf8bed493f wip logging 1 year ago
Harrison Chase ad85f3bdbc Merge branch 'master' into harrison/logger 1 year ago
Harrison Chase c2580cf401 stash 1 year ago
Harrison Chase 7ec210767a Merge branch 'master' into harrison/logger 1 year ago
Harrison Chase 2bef195a1f stash 1 year ago

@ -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": null,
"execution_count": 7,
"id": "8078c8f1",
"metadata": {},
"outputs": [
@ -46,9 +46,31 @@
"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 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 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": [
"'Bill Clinton'"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
@ -81,7 +103,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.6"
"version": "3.10.8"
}
},
"nbformat": 4,

@ -13,6 +13,7 @@ from langchain.chains import (
)
from langchain.docstore import InMemoryDocstore, Wikipedia
from langchain.llms import Cohere, HuggingFaceHub, OpenAI
from langchain.logger import BaseLogger
from langchain.prompts import (
BasePromptTemplate,
FewShotPromptTemplate,
@ -23,6 +24,8 @@ from langchain.serpapi import SerpAPIChain, SerpAPIWrapper
from langchain.sql_database import SQLDatabase
from langchain.vectorstores import FAISS, ElasticVectorSearch
logger = BaseLogger()
__all__ = [
"LLMChain",
"LLMMathChain",

@ -2,24 +2,18 @@
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.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 ChainedInput, get_color_mapping
from langchain.input import get_color_mapping
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
class Agent(Chain, BaseModel, ABC):
@ -99,7 +93,7 @@ class Agent(Chain, BaseModel, ABC):
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 +113,7 @@ class Agent(Chain, BaseModel, ABC):
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."""
@ -145,7 +139,7 @@ class Agent(Chain, BaseModel, ABC):
# 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 +148,9 @@ class Agent(Chain, BaseModel, ABC):
# 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,
self.observation_prefix,
self.llm_prefix,
color=color_mapping[output.tool],
)

@ -0,0 +1,44 @@
"""Input manager for agents."""
from typing import Optional
import langchain
from langchain.schema import AgentAction
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:
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:
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:
"""Add observation to input, print if in verbose mode."""
if self._verbose:
langchain.logger.log_agent_observation(
observation,
color=color,
observation_prefix=observation_prefix,
llm_prefix=llm_prefix,
)
self._input += f"\n{observation_prefix}{observation}\n{llm_prefix}"
@property
def input(self) -> str:
"""Return the accumulated input."""
return self._input

@ -80,7 +80,7 @@ class APIChain(Chain, BaseModel):
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,

@ -3,8 +3,8 @@ from typing import Any, Dict, List, Union
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 @@ class LLMChain(Chain, BaseModel):
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:

@ -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

@ -0,0 +1,56 @@
from typing import Any, Optional
from langchain.input import print_text
from langchain.schema import AgentAction
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
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):
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_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,
):
print_text(f"\n{observation_prefix}")
print_text(observation, color=color)
print_text(f"\n{llm_prefix}")

@ -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

@ -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

@ -3,7 +3,8 @@
import sys
from io import StringIO
from langchain.input import ChainedInput, get_color_mapping
from langchain.agents.input import ChainedInput
from langchain.input import get_color_mapping
def test_chained_input_not_verbose() -> None:

Loading…
Cancel
Save