Spaces:
Runtime error
Runtime error
"""Implement an LLM driven browser.""" | |
from __future__ import annotations | |
import warnings | |
from typing import Any, Dict, List, Optional | |
from langchain_core.language_models import BaseLanguageModel | |
from langchain_core.pydantic_v1 import Extra, root_validator | |
from langchain.callbacks.manager import CallbackManagerForChainRun | |
from langchain.chains.base import Chain | |
from langchain.chains.llm import LLMChain | |
from langchain.chains.natbot.prompt import PROMPT | |
from langchain.llms.openai import OpenAI | |
class NatBotChain(Chain): | |
"""Implement an LLM driven browser. | |
**Security Note**: This toolkit provides code to control a web-browser. | |
The web-browser can be used to navigate to: | |
- Any URL (including any internal network URLs) | |
- And local files | |
Exercise care if exposing this chain to end-users. Control who is able to | |
access and use this chain, and isolate the network access of the server | |
that hosts this chain. | |
See https://python.langchain.com/docs/security for more information. | |
Example: | |
.. code-block:: python | |
from langchain.chains import NatBotChain | |
natbot = NatBotChain.from_default("Buy me a new hat.") | |
""" | |
llm_chain: LLMChain | |
objective: str | |
"""Objective that NatBot is tasked with completing.""" | |
llm: Optional[BaseLanguageModel] = None | |
"""[Deprecated] LLM wrapper to use.""" | |
input_url_key: str = "url" #: :meta private: | |
input_browser_content_key: str = "browser_content" #: :meta private: | |
previous_command: str = "" #: :meta private: | |
output_key: str = "command" #: :meta private: | |
class Config: | |
"""Configuration for this pydantic object.""" | |
extra = Extra.forbid | |
arbitrary_types_allowed = True | |
def raise_deprecation(cls, values: Dict) -> Dict: | |
if "llm" in values: | |
warnings.warn( | |
"Directly instantiating an NatBotChain with an llm is deprecated. " | |
"Please instantiate with llm_chain argument or using the from_llm " | |
"class method." | |
) | |
if "llm_chain" not in values and values["llm"] is not None: | |
values["llm_chain"] = LLMChain(llm=values["llm"], prompt=PROMPT) | |
return values | |
def from_default(cls, objective: str, **kwargs: Any) -> NatBotChain: | |
"""Load with default LLMChain.""" | |
llm = OpenAI(temperature=0.5, best_of=10, n=3, max_tokens=50) | |
return cls.from_llm(llm, objective, **kwargs) | |
def from_llm( | |
cls, llm: BaseLanguageModel, objective: str, **kwargs: Any | |
) -> NatBotChain: | |
"""Load from LLM.""" | |
llm_chain = LLMChain(llm=llm, prompt=PROMPT) | |
return cls(llm_chain=llm_chain, objective=objective, **kwargs) | |
def input_keys(self) -> List[str]: | |
"""Expect url and browser content. | |
:meta private: | |
""" | |
return [self.input_url_key, self.input_browser_content_key] | |
def output_keys(self) -> List[str]: | |
"""Return command. | |
:meta private: | |
""" | |
return [self.output_key] | |
def _call( | |
self, | |
inputs: Dict[str, str], | |
run_manager: Optional[CallbackManagerForChainRun] = None, | |
) -> Dict[str, str]: | |
_run_manager = run_manager or CallbackManagerForChainRun.get_noop_manager() | |
url = inputs[self.input_url_key] | |
browser_content = inputs[self.input_browser_content_key] | |
llm_cmd = self.llm_chain.predict( | |
objective=self.objective, | |
url=url[:100], | |
previous_command=self.previous_command, | |
browser_content=browser_content[:4500], | |
callbacks=_run_manager.get_child(), | |
) | |
llm_cmd = llm_cmd.strip() | |
self.previous_command = llm_cmd | |
return {self.output_key: llm_cmd} | |
def execute(self, url: str, browser_content: str) -> str: | |
"""Figure out next browser command to run. | |
Args: | |
url: URL of the site currently on. | |
browser_content: Content of the page as currently displayed by the browser. | |
Returns: | |
Next browser command to run. | |
Example: | |
.. code-block:: python | |
browser_content = "...." | |
llm_command = natbot.run("www.google.com", browser_content) | |
""" | |
_inputs = { | |
self.input_url_key: url, | |
self.input_browser_content_key: browser_content, | |
} | |
return self(_inputs)[self.output_key] | |
def _chain_type(self) -> str: | |
return "nat_bot_chain" | |