Implement Runnable for Tools (#8460)

- Make _arun optional
- Pass run_manager to inner chains in tools that have them

<!-- Thank you for contributing to LangChain!

Replace this comment with:
  - Description: a description of the change, 
  - Issue: the issue # it fixes (if applicable),
  - Dependencies: any dependencies required for this change,
- Tag maintainer: for a quicker response, tag the relevant maintainer
(see below),
- Twitter handle: we announce bigger features on Twitter. If your PR
gets announced and you'd like a mention, we'll gladly shout you out!

Please make sure you're PR is passing linting and testing before
submitting. Run `make format`, `make lint` and `make test` to check this
locally.

If you're adding a new integration, please include:
1. a test for the integration, preferably unit tests that do not rely on
network access,
  2. an example notebook showing its use.

Maintainer responsibilities:
  - General / Misc / if you don't know who to tag: @baskaryan
  - DataLoaders / VectorStores / Retrievers: @rlancemartin, @eyurtsev
  - Models / Prompts: @hwchase17, @baskaryan
  - Memory: @hwchase17
  - Agents / Tools / Toolkits: @hinthornw
  - Tracing / Callbacks: @agola11
  - Async: @agola11

If no one reviews your PR within a few days, feel free to @-mention the
same people again.

See contribution guidelines for more information on how to write/run
tests, lint, etc:
https://github.com/hwchase17/langchain/blob/master/.github/CONTRIBUTING.md
 -->
This commit is contained in:
Nuno Campos 2023-07-29 18:01:18 +01:00 committed by GitHub
parent 412fa4e1db
commit 872abb4198
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
49 changed files with 147 additions and 638 deletions

View File

@ -2,10 +2,7 @@ from typing import Optional, Type
from pydantic import BaseModel, Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.chains import LLMChain
from langchain.chat_models import ChatOpenAI
from langchain.tools.amadeus.base import AmadeusBaseTool
@ -58,10 +55,3 @@ class AmadeusClosestAirport(AmadeusBaseTool):
output = llm_chain.run(location=location)
return output
async def _arun(
self,
location: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
raise NotImplementedError(f"The tool {self.name} does not support async yet.")

View File

@ -4,10 +4,7 @@ from typing import Dict, Optional, Type
from pydantic import BaseModel, Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.amadeus.base import AmadeusBaseTool
logger = logging.getLogger(__name__)
@ -153,14 +150,3 @@ class AmadeusFlightSearch(AmadeusBaseTool):
endIndex = startIndex + RESULTS_PER_PAGE
return output[startIndex:endIndex]
async def _arun(
self,
originLocationCode: str,
destinationLocationCode: str,
departureDateTimeEarliest: str,
departureDateTimeLatest: str,
page_number: int = 1,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> list:
raise NotImplementedError(f"The tool {self.name} does not support async yet.")

View File

@ -4,10 +4,7 @@ from typing import Optional
from pydantic import Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.base import BaseTool
from langchain.utilities.arxiv import ArxivAPIWrapper
@ -33,11 +30,3 @@ class ArxivQueryRun(BaseTool):
) -> str:
"""Use the Arxiv tool."""
return self.api_wrapper.run(query)
async def _arun(
self,
query: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the Arxiv tool asynchronously."""
raise NotImplementedError("ArxivAPIWrapper does not support async")

View File

@ -5,10 +5,7 @@ from typing import Any, Dict, List, Optional
from pydantic import root_validator
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.azure_cognitive_services.utils import detect_file_src_type
from langchain.tools.base import BaseTool
from langchain.utils import get_from_dict_or_env
@ -142,11 +139,3 @@ class AzureCogsFormRecognizerTool(BaseTool):
return self._format_document_analysis_result(document_analysis_result)
except Exception as e:
raise RuntimeError(f"Error while running AzureCogsFormRecognizerTool: {e}")
async def _arun(
self,
query: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the tool asynchronously."""
raise NotImplementedError("AzureCogsFormRecognizerTool does not support async")

View File

@ -5,10 +5,7 @@ from typing import Any, Dict, Optional
from pydantic import root_validator
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.azure_cognitive_services.utils import detect_file_src_type
from langchain.tools.base import BaseTool
from langchain.utils import get_from_dict_or_env
@ -146,11 +143,3 @@ class AzureCogsImageAnalysisTool(BaseTool):
return self._format_image_analysis_result(image_analysis_result)
except Exception as e:
raise RuntimeError(f"Error while running AzureCogsImageAnalysisTool: {e}")
async def _arun(
self,
query: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the tool asynchronously."""
raise NotImplementedError("AzureCogsImageAnalysisTool does not support async")

View File

@ -6,10 +6,7 @@ from typing import Any, Dict, Optional
from pydantic import root_validator
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.azure_cognitive_services.utils import (
detect_file_src_type,
download_audio_from_url,
@ -121,11 +118,3 @@ class AzureCogsSpeech2TextTool(BaseTool):
return text
except Exception as e:
raise RuntimeError(f"Error while running AzureCogsSpeech2TextTool: {e}")
async def _arun(
self,
query: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the tool asynchronously."""
raise NotImplementedError("AzureCogsSpeech2TextTool does not support async")

View File

@ -6,10 +6,7 @@ from typing import Any, Dict, Optional
from pydantic import root_validator
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.base import BaseTool
from langchain.utils import get_from_dict_or_env
@ -104,11 +101,3 @@ class AzureCogsText2SpeechTool(BaseTool):
return speech_file
except Exception as e:
raise RuntimeError(f"Error while running AzureCogsText2SpeechTool: {e}")
async def _arun(
self,
query: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the tool asynchronously."""
raise NotImplementedError("AzureCogsText2SpeechTool does not support async")

View File

@ -1,8 +1,10 @@
"""Base implementation for tools or skills."""
from __future__ import annotations
import asyncio
import warnings
from abc import ABC, abstractmethod
from abc import abstractmethod
from functools import partial
from inspect import signature
from typing import Any, Awaitable, Callable, Dict, List, Optional, Tuple, Type, Union
@ -24,6 +26,7 @@ from langchain.callbacks.manager import (
CallbackManagerForToolRun,
Callbacks,
)
from langchain.schema.runnable import Runnable, RunnableConfig
class SchemaAnnotationError(TypeError):
@ -129,7 +132,7 @@ class ToolException(Exception):
pass
class BaseTool(ABC, BaseModel, metaclass=ToolMetaclass):
class BaseTool(BaseModel, Runnable[Union[str, Dict], Any], metaclass=ToolMetaclass):
"""Interface LangChain tools must implement."""
name: str
@ -191,6 +194,32 @@ class BaseTool(ABC, BaseModel, metaclass=ToolMetaclass):
schema = create_schema_from_function(self.name, self._run)
return schema.schema()["properties"]
# --- Runnable ---
def invoke(
self,
input: Union[str, Dict],
config: Optional[RunnableConfig] = None,
**kwargs: Any,
) -> Any:
config = config or {}
return self.run(input, **config, **kwargs)
async def ainvoke(
self,
input: Union[str, Dict],
config: Optional[RunnableConfig] = None,
**kwargs: Any,
) -> Any:
if type(self)._arun == BaseTool._arun:
# If the tool does not implement async, fall back to default implementation
return super().ainvoke(input, config, **kwargs)
config = config or {}
return await self.arun(input, **config, **kwargs)
# --- Tool ---
def _parse_input(
self,
tool_input: Union[str, Dict],
@ -231,7 +260,6 @@ class BaseTool(ABC, BaseModel, metaclass=ToolMetaclass):
to child implementations to enable tracing,
"""
@abstractmethod
async def _arun(
self,
*args: Any,
@ -242,6 +270,7 @@ class BaseTool(ABC, BaseModel, metaclass=ToolMetaclass):
Add run_manager: Optional[AsyncCallbackManagerForToolRun] = None
to child implementations to enable tracing,
"""
raise NotImplementedError()
def _to_args_and_kwargs(self, tool_input: Union[str, Dict]) -> Tuple[Tuple, Dict]:
# For backwards compatibility, if run_input is a string,
@ -411,6 +440,24 @@ class Tool(BaseTool):
coroutine: Optional[Callable[..., Awaitable[str]]] = None
"""The asynchronous version of the function."""
# --- Runnable ---
async def ainvoke(
self,
input: Union[str, Dict],
config: Optional[RunnableConfig] = None,
**kwargs: Any,
) -> Any:
if not self.coroutine:
# If the tool does not implement async, fall back to default implementation
return await asyncio.get_running_loop().run_in_executor(
None, partial(self.invoke, input, config, **kwargs)
)
return super().ainvoke(input, config, **kwargs)
# --- Tool ---
@property
def args(self) -> dict:
"""The tool's input arguments."""
@ -513,6 +560,24 @@ class StructuredTool(BaseTool):
coroutine: Optional[Callable[..., Awaitable[Any]]] = None
"""The asynchronous version of the function."""
# --- Runnable ---
async def ainvoke(
self,
input: Union[str, Dict],
config: Optional[RunnableConfig] = None,
**kwargs: Any,
) -> Any:
if not self.coroutine:
# If the tool does not implement async, fall back to default implementation
return await asyncio.get_running_loop().run_in_executor(
None, partial(self.invoke, input, config, **kwargs)
)
return super().ainvoke(input, config, **kwargs)
# --- Tool ---
@property
def args(self) -> dict:
"""The tool's input arguments."""

View File

@ -2,10 +2,7 @@
from typing import Optional
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.base import BaseTool
from langchain.utilities.bing_search import BingSearchAPIWrapper
@ -29,14 +26,6 @@ class BingSearchRun(BaseTool):
"""Use the tool."""
return self.api_wrapper.run(query)
async def _arun(
self,
query: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the tool asynchronously."""
raise NotImplementedError("BingSearchRun does not support async")
class BingSearchResults(BaseTool):
"""Tool that queries the Bing Search API and gets back json."""
@ -57,11 +46,3 @@ class BingSearchResults(BaseTool):
) -> str:
"""Use the tool."""
return str(self.api_wrapper.results(query, self.num_results))
async def _arun(
self,
query: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the tool asynchronously."""
raise NotImplementedError("BingSearchResults does not support async")

View File

@ -2,10 +2,7 @@ from __future__ import annotations
from typing import Any, Optional
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.base import BaseTool
from langchain.utilities.brave_search import BraveSearchWrapper
@ -45,11 +42,3 @@ class BraveSearch(BaseTool):
) -> str:
"""Use the tool."""
return self.search_wrapper.run(query)
async def _arun(
self,
query: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the tool asynchronously."""
raise NotImplementedError("BraveSearch does not support async")

View File

@ -5,10 +5,7 @@ from typing import Any, Optional
from pydantic import Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.base import BaseTool
from langchain.utilities.duckduckgo_search import DuckDuckGoSearchAPIWrapper
@ -34,14 +31,6 @@ class DuckDuckGoSearchRun(BaseTool):
"""Use the tool."""
return self.api_wrapper.run(query)
async def _arun(
self,
query: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the tool asynchronously."""
raise NotImplementedError("DuckDuckGoSearch does not support async")
class DuckDuckGoSearchResults(BaseTool):
"""Tool that queries the DuckDuckGo search API and gets back json."""
@ -68,14 +57,6 @@ class DuckDuckGoSearchResults(BaseTool):
res_strs = [", ".join([f"{k}: {v}" for k, v in d.items()]) for d in res]
return ", ".join([f"[{rs}]" for rs in res_strs])
async def _arun(
self,
query: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the tool asynchronously."""
raise NotImplementedError("DuckDuckGoSearchResults does not support async")
def DuckDuckGoSearchTool(*args: Any, **kwargs: Any) -> DuckDuckGoSearchRun:
"""

View File

@ -3,10 +3,7 @@ from typing import Optional, Type
from pydantic import BaseModel, Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.base import BaseTool
from langchain.tools.file_management.utils import (
INVALID_PATH_TEMPLATE,
@ -53,11 +50,4 @@ class CopyFileTool(BaseFileToolMixin, BaseTool):
except Exception as e:
return "Error: " + str(e)
async def _arun(
self,
source_path: str,
destination_path: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
# TODO: Add aiofiles method
raise NotImplementedError
# TODO: Add aiofiles method

View File

@ -3,10 +3,7 @@ from typing import Optional, Type
from pydantic import BaseModel, Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.base import BaseTool
from langchain.tools.file_management.utils import (
INVALID_PATH_TEMPLATE,
@ -45,10 +42,4 @@ class DeleteFileTool(BaseFileToolMixin, BaseTool):
except Exception as e:
return "Error: " + str(e)
async def _arun(
self,
file_path: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
# TODO: Add aiofiles method
raise NotImplementedError
# TODO: Add aiofiles method

View File

@ -4,10 +4,7 @@ from typing import Optional, Type
from pydantic import BaseModel, Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.base import BaseTool
from langchain.tools.file_management.utils import (
INVALID_PATH_TEMPLATE,
@ -62,11 +59,4 @@ class FileSearchTool(BaseFileToolMixin, BaseTool):
except Exception as e:
return "Error: " + str(e)
async def _arun(
self,
dir_path: str,
pattern: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
# TODO: Add aiofiles method
raise NotImplementedError
# TODO: Add aiofiles method

View File

@ -3,10 +3,7 @@ from typing import Optional, Type
from pydantic import BaseModel, Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.base import BaseTool
from langchain.tools.file_management.utils import (
INVALID_PATH_TEMPLATE,
@ -46,10 +43,4 @@ class ListDirectoryTool(BaseFileToolMixin, BaseTool):
except Exception as e:
return "Error: " + str(e)
async def _arun(
self,
dir_path: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
# TODO: Add aiofiles method
raise NotImplementedError
# TODO: Add aiofiles method

View File

@ -3,10 +3,7 @@ from typing import Optional, Type
from pydantic import BaseModel, Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.base import BaseTool
from langchain.tools.file_management.utils import (
INVALID_PATH_TEMPLATE,
@ -56,11 +53,4 @@ class MoveFileTool(BaseFileToolMixin, BaseTool):
except Exception as e:
return "Error: " + str(e)
async def _arun(
self,
source_path: str,
destination_path: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
# TODO: Add aiofiles method
raise NotImplementedError
# TODO: Add aiofiles method

View File

@ -2,10 +2,7 @@ from typing import Optional, Type
from pydantic import BaseModel, Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.base import BaseTool
from langchain.tools.file_management.utils import (
INVALID_PATH_TEMPLATE,
@ -45,10 +42,4 @@ class ReadFileTool(BaseFileToolMixin, BaseTool):
except Exception as e:
return "Error: " + str(e)
async def _arun(
self,
file_path: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
# TODO: Add aiofiles method
raise NotImplementedError
# TODO: Add aiofiles method

View File

@ -2,10 +2,7 @@ from typing import Optional, Type
from pydantic import BaseModel, Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.base import BaseTool
from langchain.tools.file_management.utils import (
INVALID_PATH_TEMPLATE,
@ -51,12 +48,4 @@ class WriteFileTool(BaseFileToolMixin, BaseTool):
except Exception as e:
return "Error: " + str(e)
async def _arun(
self,
file_path: str,
text: str,
append: bool = False,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
# TODO: Add aiofiles method
raise NotImplementedError
# TODO: Add aiofiles method

View File

@ -11,10 +11,7 @@ from typing import Optional
from pydantic import Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.base import BaseTool
from langchain.utilities.github import GitHubAPIWrapper
@ -34,11 +31,3 @@ class GitHubAction(BaseTool):
) -> str:
"""Use the GitHub API to run an operation."""
return self.api_wrapper.run(self.mode, instructions)
async def _arun(
self,
_: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the GitHub API to run an operation."""
raise NotImplementedError("GitHubAction does not support async")

View File

@ -4,10 +4,7 @@ from typing import List, Optional, Type
from pydantic import BaseModel, Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.gmail.base import GmailBaseTool
@ -88,14 +85,3 @@ class GmailCreateDraft(GmailBaseTool):
return output
except Exception as e:
raise Exception(f"An error occurred: {e}")
async def _arun(
self,
message: str,
to: List[str],
subject: str,
cc: Optional[List[str]] = None,
bcc: Optional[List[str]] = None,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
raise NotImplementedError(f"The tool {self.name} does not support async yet.")

View File

@ -4,10 +4,7 @@ from typing import Dict, Optional, Type
from pydantic import BaseModel, Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.gmail.base import GmailBaseTool
from langchain.tools.gmail.utils import clean_email_body
@ -62,11 +59,3 @@ class GmailGetMessage(GmailBaseTool):
"subject": subject,
"sender": sender,
}
async def _arun(
self,
message_id: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> Dict:
"""Run the tool."""
raise NotImplementedError

View File

@ -2,10 +2,7 @@ from typing import Dict, Optional, Type
from pydantic import BaseModel, Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.gmail.base import GmailBaseTool
@ -49,11 +46,3 @@ class GmailGetThread(GmailBaseTool):
{k: message[k] for k in keys_to_keep if k in message}
)
return thread_data
async def _arun(
self,
thread_id: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> Dict:
"""Run the tool."""
raise NotImplementedError

View File

@ -5,10 +5,7 @@ from typing import Any, Dict, List, Optional, Type
from pydantic import BaseModel, Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.gmail.base import GmailBaseTool
from langchain.tools.gmail.utils import clean_email_body
@ -132,13 +129,3 @@ class GmailSearch(GmailBaseTool):
return self._parse_messages(results)
else:
raise NotImplementedError(f"Resource of type {resource} not implemented.")
async def _arun(
self,
query: str,
resource: Resource = Resource.MESSAGES,
max_results: int = 10,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> List[Dict[str, Any]]:
"""Run the tool."""
raise NotImplementedError

View File

@ -6,10 +6,7 @@ from typing import Any, Dict, List, Optional, Union
from pydantic import BaseModel, Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.gmail.base import GmailBaseTool
@ -90,15 +87,3 @@ class GmailSendMessage(GmailBaseTool):
return f'Message sent. Message Id: {sent_message["id"]}'
except Exception as error:
raise Exception(f"An error occurred: {error}")
async def _arun(
self,
message: str,
to: Union[str, List[str]],
subject: str,
cc: Optional[Union[str, List[str]]] = None,
bcc: Optional[Union[str, List[str]]] = None,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Run the tool asynchronously."""
raise NotImplementedError(f"The tool {self.name} does not support async yet.")

View File

@ -2,10 +2,7 @@
from typing import Optional
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.base import BaseTool
from langchain.utilities.golden_query import GoldenQueryAPIWrapper
@ -34,11 +31,3 @@ class GoldenQueryRun(BaseTool):
) -> str:
"""Use the Golden tool."""
return self.api_wrapper.run(query)
async def _arun(
self,
query: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the Golden tool asynchronously."""
raise NotImplementedError("Golden does not support async")

View File

@ -4,10 +4,7 @@ from typing import Optional, Type
from pydantic import BaseModel, Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.base import BaseTool
from langchain.utilities.google_places_api import GooglePlacesAPIWrapper
@ -38,11 +35,3 @@ class GooglePlacesTool(BaseTool):
) -> str:
"""Use the tool."""
return self.api_wrapper.run(query)
async def _arun(
self,
query: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the tool asynchronously."""
raise NotImplementedError("GooglePlacesRun does not support async")

View File

@ -2,10 +2,7 @@
from typing import Optional
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.base import BaseTool
from langchain.utilities.google_search import GoogleSearchAPIWrapper
@ -29,14 +26,6 @@ class GoogleSearchRun(BaseTool):
"""Use the tool."""
return self.api_wrapper.run(query)
async def _arun(
self,
query: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the tool asynchronously."""
raise NotImplementedError("GoogleSearchRun does not support async")
class GoogleSearchResults(BaseTool):
"""Tool that queries the Google Search API and gets back json."""
@ -57,11 +46,3 @@ class GoogleSearchResults(BaseTool):
) -> str:
"""Use the tool."""
return str(self.api_wrapper.results(query, self.num_results))
async def _arun(
self,
query: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the tool asynchronously."""
raise NotImplementedError("GoogleSearchRun does not support async")

View File

@ -1,10 +1,7 @@
import json
from typing import Optional
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.base import BaseTool
from langchain.utilities.graphql import GraphQLAPIWrapper
@ -36,11 +33,3 @@ class BaseGraphQLTool(BaseTool):
) -> str:
result = self.graphql_wrapper.run(tool_input)
return json.dumps(result, indent=2)
async def _arun(
self,
tool_input: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the Graphql tool asynchronously."""
raise NotImplementedError("GraphQLAPIWrapper does not support async")

View File

@ -4,10 +4,7 @@ from typing import Callable, Optional
from pydantic import Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.base import BaseTool
@ -36,11 +33,3 @@ class HumanInputRun(BaseTool):
"""Use the Human input tool."""
self.prompt_func(query)
return self.input_func()
async def _arun(
self,
query: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the Human tool asynchronously."""
raise NotImplementedError("Human tool does not support async")

View File

@ -36,10 +36,7 @@ from typing import Optional
import requests
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.base import BaseTool
@ -62,10 +59,3 @@ class IFTTTWebhook(BaseTool):
body = {"this": tool_input}
response = requests.post(self.url, data=body)
return response.text
async def _arun(
self,
tool_input: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
raise NotImplementedError("Not implemented.")

View File

@ -32,10 +32,7 @@ from typing import Optional
from pydantic import Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.base import BaseTool
from langchain.utilities.jira import JiraAPIWrapper
@ -55,11 +52,3 @@ class JiraAction(BaseTool):
) -> str:
"""Use the Atlassian Jira API to run an operation."""
return self.api_wrapper.run(self.mode, instructions)
async def _arun(
self,
_: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the Atlassian Jira API to run an operation."""
raise NotImplementedError("JiraAction does not support async")

View File

@ -3,10 +3,7 @@ from typing import Any, Optional
from pydantic import Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.base import BaseTool
from langchain.utilities.multion import MultionClientAPIWrapper
@ -38,13 +35,3 @@ class MultionClientTool(BaseTool):
) -> str:
"""Use the tool."""
return self.api_wrapper.run(task, url, tabId)
async def _arun(
self,
task: str,
url: str,
tabId: Optional[Any] = None,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the tool asynchronously."""
raise NotImplementedError("Multion Client does not support async yet")

View File

@ -2,10 +2,7 @@ from typing import List, Optional, Type
from pydantic import BaseModel, Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.office365.base import O365BaseTool
@ -69,14 +66,3 @@ class O365CreateDraftMessage(O365BaseTool):
output = "Draft created: " + str(message)
return output
async def _arun(
self,
message: str,
to: List[str],
subject: str,
cc: Optional[List[str]] = None,
bcc: Optional[List[str]] = None,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
raise NotImplementedError(f"The tool {self.name} does not support async yet.")

View File

@ -9,10 +9,7 @@ from typing import Any, Dict, List, Optional, Type
from pydantic import BaseModel, Extra, Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.office365.base import O365BaseTool
from langchain.tools.office365.utils import clean_body
@ -130,12 +127,3 @@ class O365SearchEvents(O365BaseTool):
output_events.append(output_event)
return output_events
async def _arun(
self,
query: str,
max_results: int = 10,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> List[Dict[str, Any]]:
"""Run the tool."""
raise NotImplementedError

View File

@ -8,10 +8,7 @@ from typing import Any, Dict, List, Optional, Type
from pydantic import BaseModel, Extra, Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.office365.base import O365BaseTool
from langchain.tools.office365.utils import clean_body
@ -123,12 +120,3 @@ class O365SearchEmails(O365BaseTool):
output_messages.append(output_message)
return output_messages
async def _arun(
self,
query: str,
max_results: int = 10,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> List[Dict[str, Any]]:
"""Run the tool."""
raise NotImplementedError

View File

@ -9,10 +9,7 @@ from typing import List, Optional, Type
from pydantic import BaseModel, Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.office365.base import O365BaseTool
@ -85,14 +82,3 @@ class O365SendEvent(O365BaseTool):
output = "Event sent: " + str(event)
return output
async def _arun(
self,
message: str,
to: List[str],
subject: str,
cc: Optional[List[str]] = None,
bcc: Optional[List[str]] = None,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
raise NotImplementedError(f"The tool {self.name} does not support async yet.")

View File

@ -2,10 +2,7 @@ from typing import List, Optional, Type
from pydantic import BaseModel, Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.office365.base import O365BaseTool
@ -69,14 +66,3 @@ class O365SendMessage(O365BaseTool):
output = "Message sent: " + str(message)
return output
async def _arun(
self,
message: str,
to: List[str],
subject: str,
cc: Optional[List[str]] = None,
bcc: Optional[List[str]] = None,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
raise NotImplementedError(f"The tool {self.name} does not support async yet.")

View File

@ -4,10 +4,7 @@ from typing import Optional
from pydantic import Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.base import BaseTool
from langchain.utilities import OpenWeatherMapAPIWrapper
@ -31,11 +28,3 @@ class OpenWeatherMapQueryRun(BaseTool):
) -> str:
"""Use the OpenWeatherMap tool."""
return self.api_wrapper.run(location)
async def _arun(
self,
location: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the OpenWeatherMap tool asynchronously."""
raise NotImplementedError("OpenWeatherMapQueryRun does not support async")

View File

@ -84,6 +84,7 @@ class QueryPowerBITool(BaseTool):
tables=self.powerbi.get_table_names(),
schemas=self.powerbi.get_schemas(),
examples=self.examples,
callbacks=run_manager.get_child() if run_manager else None,
)
except Exception as exc: # pylint: disable=broad-except
self.session_cache[tool_input] = f"Error on call to LLM: {exc}"
@ -136,6 +137,7 @@ class QueryPowerBITool(BaseTool):
tables=self.powerbi.get_table_names(),
schemas=self.powerbi.get_schemas(),
examples=self.examples,
callbacks=run_manager.get_child() if run_manager else None,
)
except Exception as exc: # pylint: disable=broad-except
self.session_cache[tool_input] = f"Error on call to LLM: {exc}"

View File

@ -4,10 +4,7 @@ from typing import Optional
from pydantic import Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.base import BaseTool
from langchain.utilities.pupmed import PubMedAPIWrapper
@ -33,11 +30,3 @@ class PubmedQueryRun(BaseTool):
) -> str:
"""Use the Arxiv tool."""
return self.api_wrapper.run(query)
async def _arun(
self,
query: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the PubMed tool asynchronously."""
raise NotImplementedError("PubMedAPIWrapper does not support async")

View File

@ -131,11 +131,3 @@ class PythonAstREPLTool(BaseTool):
return io_buffer.getvalue()
except Exception as e:
return "{}: {}".format(type(e).__name__, str(e))
async def _arun(
self,
query: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the tool asynchronously."""
raise NotImplementedError("PythonReplTool does not support async")

View File

@ -3,10 +3,7 @@ from typing import Optional
from pydantic import BaseModel, Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.base import BaseTool
from langchain.utilities.scenexplain import SceneXplainAPIWrapper
@ -33,9 +30,3 @@ class SceneXplainTool(BaseTool):
) -> str:
"""Use the tool."""
return self.api_wrapper.run(query)
async def _arun(
self, query: str, run_manager: Optional[AsyncCallbackManagerForToolRun] = None
) -> str:
"""Use the tool asynchronously."""
raise NotImplementedError("SceneXplainTool does not support async")

View File

@ -48,13 +48,6 @@ class QuerySparkSQLTool(BaseSparkSQLTool, BaseTool):
"""Execute the query, return the results or an error message."""
return self.db.run_no_throw(query)
async def _arun(
self,
query: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
raise NotImplementedError("QuerySqlDbTool does not support async")
class InfoSparkSQLTool(BaseSparkSQLTool, BaseTool):
"""Tool for getting metadata about a Spark SQL."""
@ -75,13 +68,6 @@ class InfoSparkSQLTool(BaseSparkSQLTool, BaseTool):
"""Get the schema for tables in a comma-separated list."""
return self.db.get_table_info_no_throw(table_names.split(", "))
async def _arun(
self,
table_name: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
raise NotImplementedError("SchemaSqlDbTool does not support async")
class ListSparkSQLTool(BaseSparkSQLTool, BaseTool):
"""Tool for getting tables names."""
@ -97,13 +83,6 @@ class ListSparkSQLTool(BaseSparkSQLTool, BaseTool):
"""Get the schema for a specific table."""
return ", ".join(self.db.get_usable_table_names())
async def _arun(
self,
tool_input: str = "",
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
raise NotImplementedError("ListTablesSqlDbTool does not support async")
class QueryCheckerTool(BaseSparkSQLTool, BaseTool):
"""Use an LLM to check if a query is correct.
@ -142,11 +121,15 @@ class QueryCheckerTool(BaseSparkSQLTool, BaseTool):
run_manager: Optional[CallbackManagerForToolRun] = None,
) -> str:
"""Use the LLM to check the query."""
return self.llm_chain.predict(query=query)
return self.llm_chain.predict(
query=query, callbacks=run_manager.get_child() if run_manager else None
)
async def _arun(
self,
query: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
return await self.llm_chain.apredict(query=query)
return await self.llm_chain.apredict(
query=query, callbacks=run_manager.get_child() if run_manager else None
)

View File

@ -48,13 +48,6 @@ class QuerySQLDataBaseTool(BaseSQLDatabaseTool, BaseTool):
"""Execute the query, return the results or an error message."""
return self.db.run_no_throw(query)
async def _arun(
self,
query: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
raise NotImplementedError("QuerySqlDbTool does not support async")
class InfoSQLDatabaseTool(BaseSQLDatabaseTool, BaseTool):
"""Tool for getting metadata about a SQL database."""
@ -74,13 +67,6 @@ class InfoSQLDatabaseTool(BaseSQLDatabaseTool, BaseTool):
"""Get the schema for tables in a comma-separated list."""
return self.db.get_table_info_no_throw(table_names.split(", "))
async def _arun(
self,
table_name: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
raise NotImplementedError("SchemaSqlDbTool does not support async")
class ListSQLDatabaseTool(BaseSQLDatabaseTool, BaseTool):
"""Tool for getting tables names."""
@ -96,13 +82,6 @@ class ListSQLDatabaseTool(BaseSQLDatabaseTool, BaseTool):
"""Get the schema for a specific table."""
return ", ".join(self.db.get_usable_table_names())
async def _arun(
self,
tool_input: str = "",
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
raise NotImplementedError("ListTablesSqlDbTool does not support async")
class QuerySQLCheckerTool(BaseSQLDatabaseTool, BaseTool):
"""Use an LLM to check if a query is correct.
@ -140,11 +119,19 @@ class QuerySQLCheckerTool(BaseSQLDatabaseTool, BaseTool):
run_manager: Optional[CallbackManagerForToolRun] = None,
) -> str:
"""Use the LLM to check the query."""
return self.llm_chain.predict(query=query, dialect=self.db.dialect)
return self.llm_chain.predict(
query=query,
dialect=self.db.dialect,
callbacks=run_manager.get_child() if run_manager else None,
)
async def _arun(
self,
query: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
return await self.llm_chain.apredict(query=query, dialect=self.db.dialect)
return await self.llm_chain.apredict(
query=query,
dialect=self.db.dialect,
callbacks=run_manager.get_child() if run_manager else None,
)

View File

@ -18,10 +18,7 @@ from typing import TYPE_CHECKING, Dict, Optional
from pydantic import root_validator
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools import BaseTool
from langchain.tools.steamship_image_generation.utils import make_image_public
from langchain.utils import get_from_dict_or_env
@ -114,11 +111,3 @@ class SteamshipImageGenerationTool(BaseTool):
return blocks[0].id
raise RuntimeError(f"[{self.name}] Tool unable to generate image!")
async def _arun(
self,
query: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the tool asynchronously."""
raise NotImplementedError("GenerateImageTool does not support async")

View File

@ -5,10 +5,7 @@ from typing import Any, Dict, Optional
from pydantic import BaseModel, Field
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.chains import RetrievalQA, RetrievalQAWithSourcesChain
from langchain.llms.openai import OpenAI
from langchain.schema.language_model import BaseLanguageModel
@ -55,15 +52,9 @@ class VectorStoreQATool(BaseVectorStoreTool, BaseTool):
chain = RetrievalQA.from_chain_type(
self.llm, retriever=self.vectorstore.as_retriever()
)
return chain.run(query)
async def _arun(
self,
query: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the tool asynchronously."""
raise NotImplementedError("VectorStoreQATool does not support async")
return chain.run(
query, callbacks=run_manager.get_child() if run_manager else None
)
class VectorStoreQAWithSourcesTool(BaseVectorStoreTool, BaseTool):
@ -91,12 +82,10 @@ class VectorStoreQAWithSourcesTool(BaseVectorStoreTool, BaseTool):
chain = RetrievalQAWithSourcesChain.from_chain_type(
self.llm, retriever=self.vectorstore.as_retriever()
)
return json.dumps(chain({chain.question_key: query}, return_only_outputs=True))
async def _arun(
self,
query: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the tool asynchronously."""
raise NotImplementedError("VectorStoreQAWithSourcesTool does not support async")
return json.dumps(
chain(
{chain.question_key: query},
return_only_outputs=True,
callbacks=run_manager.get_child() if run_manager else None,
)
)

View File

@ -2,10 +2,7 @@
from typing import Optional
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.base import BaseTool
from langchain.utilities.wikipedia import WikipediaAPIWrapper
@ -29,11 +26,3 @@ class WikipediaQueryRun(BaseTool):
) -> str:
"""Use the Wikipedia tool."""
return self.api_wrapper.run(query)
async def _arun(
self,
query: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the Wikipedia tool asynchronously."""
raise NotImplementedError("WikipediaQueryRun does not support async")

View File

@ -2,10 +2,7 @@
from typing import Optional
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools.base import BaseTool
from langchain.utilities.wolfram_alpha import WolframAlphaAPIWrapper
@ -29,11 +26,3 @@ class WolframAlphaQueryRun(BaseTool):
) -> str:
"""Use the WolframAlpha tool."""
return self.api_wrapper.run(query)
async def _arun(
self,
query: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the WolframAlpha tool asynchronously."""
raise NotImplementedError("WolframAlphaQueryRun does not support async")

View File

@ -11,10 +11,7 @@ Input to this tool should be a comma separated list,
import json
from typing import Optional
from langchain.callbacks.manager import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain.callbacks.manager import CallbackManagerForToolRun
from langchain.tools import BaseTool
@ -51,11 +48,3 @@ class YouTubeSearchTool(BaseTool):
else:
num_results = 2
return self._search(person, num_results)
async def _arun(
self,
query: str,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
) -> str:
"""Use the tool asynchronously."""
raise NotImplementedError("YouTubeSearchTool does not yet support async")