Skip to content

Commit 443a893

Browse files
authored
Align names of search tools (langchain-ai#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.
1 parent aa345a4 commit 443a893

File tree

9 files changed

+84
-20
lines changed

9 files changed

+84
-20
lines changed

docs/modules/agents/tools/examples/ddg.ipynb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"metadata": {},
2828
"outputs": [],
2929
"source": [
30-
"from langchain.tools import DuckDuckGoSearchTool"
30+
"from langchain.tools import DuckDuckGoSearchRun"
3131
]
3232
},
3333
{
@@ -37,7 +37,7 @@
3737
"metadata": {},
3838
"outputs": [],
3939
"source": [
40-
"search = DuckDuckGoSearchTool()"
40+
"search = DuckDuckGoSearchRun()"
4141
]
4242
},
4343
{

docs/use_cases/autonomous_agents/marathon_times.ipynb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@
219219
},
220220
"outputs": [],
221221
"source": [
222-
"from langchain.tools import BaseTool, DuckDuckGoSearchTool\n",
222+
"from langchain.tools import BaseTool, DuckDuckGoSearchRun\n",
223223
"from langchain.text_splitter import RecursiveCharacterTextSplitter\n",
224224
"\n",
225225
"from pydantic import Field\n",
@@ -321,7 +321,7 @@
321321
"outputs": [],
322322
"source": [
323323
"# !pip install duckduckgo_search\n",
324-
"web_search = DuckDuckGoSearchTool()"
324+
"web_search = DuckDuckGoSearchRun()"
325325
]
326326
},
327327
{
@@ -618,7 +618,7 @@
618618
"name": "python",
619619
"nbconvert_exporter": "python",
620620
"pygments_lexer": "ipython3",
621-
"version": "3.11.2"
621+
"version": "3.8.16"
622622
}
623623
},
624624
"nbformat": 4,

langchain/agents/load_tools.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from langchain.tools.arxiv.tool import ArxivQueryRun
1616
from langchain.tools.base import BaseTool
1717
from langchain.tools.bing_search.tool import BingSearchRun
18-
from langchain.tools.ddg_search.tool import DuckDuckGoSearchTool
18+
from langchain.tools.ddg_search.tool import DuckDuckGoSearchRun
1919
from langchain.tools.google_search.tool import GoogleSearchResults, GoogleSearchRun
2020
from langchain.tools.human.tool import HumanInputRun
2121
from langchain.tools.python.tool import PythonREPLTool
@@ -219,7 +219,7 @@ def _get_bing_search(**kwargs: Any) -> BaseTool:
219219

220220

221221
def _get_ddg_search(**kwargs: Any) -> BaseTool:
222-
return DuckDuckGoSearchTool(api_wrapper=DuckDuckGoSearchAPIWrapper(**kwargs))
222+
return DuckDuckGoSearchRun(api_wrapper=DuckDuckGoSearchAPIWrapper(**kwargs))
223223

224224

225225
def _get_human_tool(**kwargs: Any) -> BaseTool:

langchain/tools/__init__.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,27 @@
11
"""Core toolkit implementations."""
22

33
from langchain.tools.base import BaseTool
4-
from langchain.tools.ddg_search.tool import DuckDuckGoSearchTool
4+
from langchain.tools.bing_search.tool import BingSearchResults, BingSearchRun
5+
from langchain.tools.ddg_search.tool import DuckDuckGoSearchResults, DuckDuckGoSearchRun
56
from langchain.tools.google_places.tool import GooglePlacesTool
7+
from langchain.tools.google_search.tool import GoogleSearchResults, GoogleSearchRun
68
from langchain.tools.ifttt import IFTTTWebhook
79
from langchain.tools.openapi.utils.api_models import APIOperation
810
from langchain.tools.openapi.utils.openapi_utils import OpenAPISpec
911
from langchain.tools.plugin import AIPluginTool
1012

1113
__all__ = [
12-
"BaseTool",
13-
"IFTTTWebhook",
1414
"AIPluginTool",
15-
"OpenAPISpec",
1615
"APIOperation",
16+
"BingSearchResults",
17+
"BingSearchRun",
18+
"DuckDuckGoSearchResults",
19+
"DuckDuckGoSearchRun",
20+
"DuckDuckGoSearchRun",
1721
"GooglePlacesTool",
18-
"DuckDuckGoSearchTool",
22+
"GoogleSearchResults",
23+
"GoogleSearchRun",
24+
"IFTTTWebhook",
25+
"OpenAPISpec",
26+
"BaseTool",
1927
]

langchain/tools/bing_search/tool.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,24 @@ def _run(self, query: str) -> str:
2222
async def _arun(self, query: str) -> str:
2323
"""Use the tool asynchronously."""
2424
raise NotImplementedError("BingSearchRun does not support async")
25+
26+
27+
class BingSearchResults(BaseTool):
28+
"""Tool that has capability to query the Bing Search API and get back json."""
29+
30+
name = "Bing Search Results JSON"
31+
description = (
32+
"A wrapper around Bing Search. "
33+
"Useful for when you need to answer questions about current events. "
34+
"Input should be a search query. Output is a JSON array of the query results"
35+
)
36+
num_results: int = 4
37+
api_wrapper: BingSearchAPIWrapper
38+
39+
def _run(self, query: str) -> str:
40+
"""Use the tool."""
41+
return str(self.api_wrapper.results(query, self.num_results))
42+
43+
async def _arun(self, query: str) -> str:
44+
"""Use the tool asynchronously."""
45+
raise NotImplementedError("BingSearchResults does not support async")
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""DuckDuckGo Search API toolkit."""
22

3-
from langchain.tools.ddg_search.tool import DuckDuckGoSearchTool
3+
from langchain.tools.ddg_search.tool import DuckDuckGoSearchRun
44

5-
__all__ = ["DuckDuckGoSearchTool"]
5+
__all__ = ["DuckDuckGoSearchRun"]

langchain/tools/ddg_search/tool.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
"""Tool for the DuckDuckGo search API."""
22

3+
import warnings
4+
from typing import Any
5+
36
from pydantic import Field
47

58
from langchain.tools.base import BaseTool
69
from langchain.utilities.duckduckgo_search import DuckDuckGoSearchAPIWrapper
710

811

9-
class DuckDuckGoSearchTool(BaseTool):
12+
class DuckDuckGoSearchRun(BaseTool):
1013
"""Tool that adds the capability to query the DuckDuckGo search API."""
1114

1215
name = "DuckDuckGo Search"
@@ -26,3 +29,35 @@ def _run(self, query: str) -> str:
2629
async def _arun(self, query: str) -> str:
2730
"""Use the tool asynchronously."""
2831
raise NotImplementedError("DuckDuckGoSearch does not support async")
32+
33+
34+
class DuckDuckGoSearchResults(BaseTool):
35+
"""Tool that queries the Duck Duck Go Search API and get back json."""
36+
37+
name = "DuckDuckGo Results JSON"
38+
description = (
39+
"A wrapper around Duck Duck Go Search. "
40+
"Useful for when you need to answer questions about current events. "
41+
"Input should be a search query. Output is a JSON array of the query results"
42+
)
43+
num_results: int = 4
44+
api_wrapper: DuckDuckGoSearchAPIWrapper = Field(
45+
default_factory=DuckDuckGoSearchAPIWrapper
46+
)
47+
48+
def _run(self, query: str) -> str:
49+
"""Use the tool."""
50+
return str(self.api_wrapper.results(query, self.num_results))
51+
52+
async def _arun(self, query: str) -> str:
53+
"""Use the tool asynchronously."""
54+
raise NotImplementedError("DuckDuckGoSearchResults does not support async")
55+
56+
57+
def DuckDuckGoSearchTool(*args: Any, **kwargs: Any) -> DuckDuckGoSearchRun:
58+
warnings.warn(
59+
"DuckDuckGoSearchTool will be deprecated in the future. "
60+
"Please use DuckDuckGoSearchRun instead.",
61+
DeprecationWarning,
62+
)
63+
return DuckDuckGoSearchRun(*args, **kwargs)

langchain/utilities/duckduckgo_search.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def validate_environment(cls, values: Dict) -> Dict:
4141
def run(self, query: str) -> str:
4242
from duckduckgo_search import ddg
4343

44-
"""Run query through DuckDuckGo and return results."""
44+
"""Run query through DuckDuckGo and return concatenated results."""
4545
results = ddg(
4646
query,
4747
region=self.region,
@@ -54,7 +54,7 @@ def run(self, query: str) -> str:
5454
snippets = [result["body"] for result in results]
5555
return " ".join(snippets)
5656

57-
def results(self, query: str, num_results: int) -> List[Dict]:
57+
def results(self, query: str, num_results: int) -> List[Dict[str, str]]:
5858
"""Run query through DuckDuckGo and return metadata.
5959
6060
Args:
@@ -80,7 +80,7 @@ def results(self, query: str, num_results: int) -> List[Dict]:
8080
if results is None or len(results) == 0:
8181
return [{"Result": "No good DuckDuckGo Search Result was found"}]
8282

83-
def to_metadata(result: Dict) -> Dict:
83+
def to_metadata(result: Dict) -> Dict[str, str]:
8484
return {
8585
"snippet": result["body"],
8686
"title": result["title"],

tests/integration_tests/utilities/test_duckduckdgo_search_api.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import pytest
22

3-
from langchain.tools.ddg_search.tool import DuckDuckGoSearchTool
3+
from langchain.tools.ddg_search.tool import DuckDuckGoSearchRun
44

55

66
def ddg_installed() -> bool:
@@ -16,7 +16,7 @@ def ddg_installed() -> bool:
1616
@pytest.mark.skipif(not ddg_installed(), reason="requires duckduckgo-search package")
1717
def test_ddg_search_tool() -> None:
1818
keywords = "Bella Ciao"
19-
tool = DuckDuckGoSearchTool()
19+
tool = DuckDuckGoSearchRun()
2020
result = tool(keywords)
2121
print(result)
2222
assert len(result.split()) > 20

0 commit comments

Comments
 (0)