Align names of search tools (#3620)

Tools for Bing, DDG and Google weren't consistent even though the
underlying implementations were.
All three services now have the same tools and implementations to easily
switch and experiment when building chains.
fix_agent_callbacks
Zander Chase 1 year ago committed by GitHub
parent aa345a4bb7
commit 443a893ffd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -27,7 +27,7 @@
"metadata": {},
"outputs": [],
"source": [
"from langchain.tools import DuckDuckGoSearchTool"
"from langchain.tools import DuckDuckGoSearchRun"
]
},
{
@ -37,7 +37,7 @@
"metadata": {},
"outputs": [],
"source": [
"search = DuckDuckGoSearchTool()"
"search = DuckDuckGoSearchRun()"
]
},
{

@ -219,7 +219,7 @@
},
"outputs": [],
"source": [
"from langchain.tools import BaseTool, DuckDuckGoSearchTool\n",
"from langchain.tools import BaseTool, DuckDuckGoSearchRun\n",
"from langchain.text_splitter import RecursiveCharacterTextSplitter\n",
"\n",
"from pydantic import Field\n",
@ -321,7 +321,7 @@
"outputs": [],
"source": [
"# !pip install duckduckgo_search\n",
"web_search = DuckDuckGoSearchTool()"
"web_search = DuckDuckGoSearchRun()"
]
},
{
@ -618,7 +618,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.2"
"version": "3.8.16"
}
},
"nbformat": 4,

@ -15,7 +15,7 @@ from langchain.requests import TextRequestsWrapper
from langchain.tools.arxiv.tool import ArxivQueryRun
from langchain.tools.base import BaseTool
from langchain.tools.bing_search.tool import BingSearchRun
from langchain.tools.ddg_search.tool import DuckDuckGoSearchTool
from langchain.tools.ddg_search.tool import DuckDuckGoSearchRun
from langchain.tools.google_search.tool import GoogleSearchResults, GoogleSearchRun
from langchain.tools.human.tool import HumanInputRun
from langchain.tools.python.tool import PythonREPLTool
@ -219,7 +219,7 @@ def _get_bing_search(**kwargs: Any) -> BaseTool:
def _get_ddg_search(**kwargs: Any) -> BaseTool:
return DuckDuckGoSearchTool(api_wrapper=DuckDuckGoSearchAPIWrapper(**kwargs))
return DuckDuckGoSearchRun(api_wrapper=DuckDuckGoSearchAPIWrapper(**kwargs))
def _get_human_tool(**kwargs: Any) -> BaseTool:

@ -1,19 +1,27 @@
"""Core toolkit implementations."""
from langchain.tools.base import BaseTool
from langchain.tools.ddg_search.tool import DuckDuckGoSearchTool
from langchain.tools.bing_search.tool import BingSearchResults, BingSearchRun
from langchain.tools.ddg_search.tool import DuckDuckGoSearchResults, DuckDuckGoSearchRun
from langchain.tools.google_places.tool import GooglePlacesTool
from langchain.tools.google_search.tool import GoogleSearchResults, GoogleSearchRun
from langchain.tools.ifttt import IFTTTWebhook
from langchain.tools.openapi.utils.api_models import APIOperation
from langchain.tools.openapi.utils.openapi_utils import OpenAPISpec
from langchain.tools.plugin import AIPluginTool
__all__ = [
"BaseTool",
"IFTTTWebhook",
"AIPluginTool",
"OpenAPISpec",
"APIOperation",
"BingSearchResults",
"BingSearchRun",
"DuckDuckGoSearchResults",
"DuckDuckGoSearchRun",
"DuckDuckGoSearchRun",
"GooglePlacesTool",
"DuckDuckGoSearchTool",
"GoogleSearchResults",
"GoogleSearchRun",
"IFTTTWebhook",
"OpenAPISpec",
"BaseTool",
]

@ -22,3 +22,24 @@ class BingSearchRun(BaseTool):
async def _arun(self, query: str) -> str:
"""Use the tool asynchronously."""
raise NotImplementedError("BingSearchRun does not support async")
class BingSearchResults(BaseTool):
"""Tool that has capability to query the Bing Search API and get back json."""
name = "Bing Search Results JSON"
description = (
"A wrapper around Bing Search. "
"Useful for when you need to answer questions about current events. "
"Input should be a search query. Output is a JSON array of the query results"
)
num_results: int = 4
api_wrapper: BingSearchAPIWrapper
def _run(self, query: str) -> str:
"""Use the tool."""
return str(self.api_wrapper.results(query, self.num_results))
async def _arun(self, query: str) -> str:
"""Use the tool asynchronously."""
raise NotImplementedError("BingSearchResults does not support async")

@ -1,5 +1,5 @@
"""DuckDuckGo Search API toolkit."""
from langchain.tools.ddg_search.tool import DuckDuckGoSearchTool
from langchain.tools.ddg_search.tool import DuckDuckGoSearchRun
__all__ = ["DuckDuckGoSearchTool"]
__all__ = ["DuckDuckGoSearchRun"]

@ -1,12 +1,15 @@
"""Tool for the DuckDuckGo search API."""
import warnings
from typing import Any
from pydantic import Field
from langchain.tools.base import BaseTool
from langchain.utilities.duckduckgo_search import DuckDuckGoSearchAPIWrapper
class DuckDuckGoSearchTool(BaseTool):
class DuckDuckGoSearchRun(BaseTool):
"""Tool that adds the capability to query the DuckDuckGo search API."""
name = "DuckDuckGo Search"
@ -26,3 +29,35 @@ class DuckDuckGoSearchTool(BaseTool):
async def _arun(self, query: str) -> str:
"""Use the tool asynchronously."""
raise NotImplementedError("DuckDuckGoSearch does not support async")
class DuckDuckGoSearchResults(BaseTool):
"""Tool that queries the Duck Duck Go Search API and get back json."""
name = "DuckDuckGo Results JSON"
description = (
"A wrapper around Duck Duck Go Search. "
"Useful for when you need to answer questions about current events. "
"Input should be a search query. Output is a JSON array of the query results"
)
num_results: int = 4
api_wrapper: DuckDuckGoSearchAPIWrapper = Field(
default_factory=DuckDuckGoSearchAPIWrapper
)
def _run(self, query: str) -> str:
"""Use the tool."""
return str(self.api_wrapper.results(query, self.num_results))
async def _arun(self, query: str) -> str:
"""Use the tool asynchronously."""
raise NotImplementedError("DuckDuckGoSearchResults does not support async")
def DuckDuckGoSearchTool(*args: Any, **kwargs: Any) -> DuckDuckGoSearchRun:
warnings.warn(
"DuckDuckGoSearchTool will be deprecated in the future. "
"Please use DuckDuckGoSearchRun instead.",
DeprecationWarning,
)
return DuckDuckGoSearchRun(*args, **kwargs)

@ -41,7 +41,7 @@ class DuckDuckGoSearchAPIWrapper(BaseModel):
def run(self, query: str) -> str:
from duckduckgo_search import ddg
"""Run query through DuckDuckGo and return results."""
"""Run query through DuckDuckGo and return concatenated results."""
results = ddg(
query,
region=self.region,
@ -54,7 +54,7 @@ class DuckDuckGoSearchAPIWrapper(BaseModel):
snippets = [result["body"] for result in results]
return " ".join(snippets)
def results(self, query: str, num_results: int) -> List[Dict]:
def results(self, query: str, num_results: int) -> List[Dict[str, str]]:
"""Run query through DuckDuckGo and return metadata.
Args:
@ -80,7 +80,7 @@ class DuckDuckGoSearchAPIWrapper(BaseModel):
if results is None or len(results) == 0:
return [{"Result": "No good DuckDuckGo Search Result was found"}]
def to_metadata(result: Dict) -> Dict:
def to_metadata(result: Dict) -> Dict[str, str]:
return {
"snippet": result["body"],
"title": result["title"],

@ -1,6 +1,6 @@
import pytest
from langchain.tools.ddg_search.tool import DuckDuckGoSearchTool
from langchain.tools.ddg_search.tool import DuckDuckGoSearchRun
def ddg_installed() -> bool:
@ -16,7 +16,7 @@ def ddg_installed() -> bool:
@pytest.mark.skipif(not ddg_installed(), reason="requires duckduckgo-search package")
def test_ddg_search_tool() -> None:
keywords = "Bella Ciao"
tool = DuckDuckGoSearchTool()
tool = DuckDuckGoSearchRun()
result = tool(keywords)
print(result)
assert len(result.split()) > 20

Loading…
Cancel
Save