diff --git a/docs/modules/agents/tools/examples/ddg.ipynb b/docs/modules/agents/tools/examples/ddg.ipynb index ea7a66ea..b37e2cdf 100644 --- a/docs/modules/agents/tools/examples/ddg.ipynb +++ b/docs/modules/agents/tools/examples/ddg.ipynb @@ -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()" ] }, { diff --git a/docs/use_cases/autonomous_agents/marathon_times.ipynb b/docs/use_cases/autonomous_agents/marathon_times.ipynb index 49d75761..aba7a9e4 100644 --- a/docs/use_cases/autonomous_agents/marathon_times.ipynb +++ b/docs/use_cases/autonomous_agents/marathon_times.ipynb @@ -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, diff --git a/langchain/agents/load_tools.py b/langchain/agents/load_tools.py index de057275..ade98c96 100644 --- a/langchain/agents/load_tools.py +++ b/langchain/agents/load_tools.py @@ -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: diff --git a/langchain/tools/__init__.py b/langchain/tools/__init__.py index 3c034f83..7ffcd0db 100644 --- a/langchain/tools/__init__.py +++ b/langchain/tools/__init__.py @@ -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", ] diff --git a/langchain/tools/bing_search/tool.py b/langchain/tools/bing_search/tool.py index c851c3ee..dd57295c 100644 --- a/langchain/tools/bing_search/tool.py +++ b/langchain/tools/bing_search/tool.py @@ -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") diff --git a/langchain/tools/ddg_search/__init__.py b/langchain/tools/ddg_search/__init__.py index 931d4a89..157811df 100644 --- a/langchain/tools/ddg_search/__init__.py +++ b/langchain/tools/ddg_search/__init__.py @@ -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"] diff --git a/langchain/tools/ddg_search/tool.py b/langchain/tools/ddg_search/tool.py index 33044241..5948756f 100644 --- a/langchain/tools/ddg_search/tool.py +++ b/langchain/tools/ddg_search/tool.py @@ -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) diff --git a/langchain/utilities/duckduckgo_search.py b/langchain/utilities/duckduckgo_search.py index 547847b9..ff6ba6e2 100644 --- a/langchain/utilities/duckduckgo_search.py +++ b/langchain/utilities/duckduckgo_search.py @@ -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"], diff --git a/tests/integration_tests/utilities/test_duckduckdgo_search_api.py b/tests/integration_tests/utilities/test_duckduckdgo_search_api.py index a6397251..8d228e57 100644 --- a/tests/integration_tests/utilities/test_duckduckdgo_search_api.py +++ b/tests/integration_tests/utilities/test_duckduckdgo_search_api.py @@ -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