diff --git a/docs/ecosystem/openweathermap.md b/docs/ecosystem/openweathermap.md new file mode 100644 index 00000000..2596ee8d --- /dev/null +++ b/docs/ecosystem/openweathermap.md @@ -0,0 +1,34 @@ +# OpenWeatherMap API + +This page covers how to use the OpenWeatherMap API within LangChain. +It is broken into two parts: installation and setup, and then references to specific OpenWeatherMap API wrappers. + +## Installation and Setup + +- Install requirements with `pip install pyowm` +- Go to OpenWeatherMap and sign up for an account to get your API key [here](https://openweathermap.org/api/) +- Set your API key as `OPENWEATHERMAP_API_KEY` environment variable + +## Wrappers + +### Utility + +There exists a OpenWeatherMapAPIWrapper utility which wraps this API. To import this utility: + +```python +from langchain.utilities.openweathermap import OpenWeatherMapAPIWrapper +``` + +For a more detailed walkthrough of this wrapper, see [this notebook](../modules/agents/tools/examples/openweathermap.ipynb). + +### Tool + +You can also easily load this wrapper as a Tool (to use with an Agent). +You can do this with: + +```python +from langchain.agents import load_tools +tools = load_tools(["openweathermap-api"]) +``` + +For more information on this, see [this page](../modules/agents/tools/getting_started.md) diff --git a/docs/modules/agents/tools/examples/openweathermap.ipynb b/docs/modules/agents/tools/examples/openweathermap.ipynb index 637daa0f..8813234c 100644 --- a/docs/modules/agents/tools/examples/openweathermap.ipynb +++ b/docs/modules/agents/tools/examples/openweathermap.ipynb @@ -1,128 +1,173 @@ { - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "id": "245a954a", - "metadata": {}, - "source": [ - "# OpenWeatherMap API\n", - "\n", - "This notebook goes over how to use the OpenWeatherMap component to fetch weather information.\n", - "\n", - "First, you need to sign up for an OpenWeatherMap API key:\n", - "\n", - "1. Go to OpenWeatherMap and sign up for an API key [here](https://openweathermap.org/api/)\n", - "2. pip install pyowm\n", - "\n", - "Then we will need to set some environment variables:\n", - "1. Save your API KEY into OPENWEATHERMAP_API_KEY env variable" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "961b3689", - "metadata": { - "vscode": { - "languageId": "shellscript" - } - }, - "outputs": [], - "source": [ - "pip install pyowm" - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "id": "34bb5968", - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "os.environ[\"OPENWEATHERMAP_API_KEY\"] = \"\"" - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "id": "ac4910f8", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.utilities import OpenWeatherMapAPIWrapper" - ] - }, + "cells": [ + { + "cell_type": "markdown", + "id": "245a954a", + "metadata": {}, + "source": [ + "# OpenWeatherMap API\n", + "\n", + "This notebook goes over how to use the OpenWeatherMap component to fetch weather information.\n", + "\n", + "First, you need to sign up for an OpenWeatherMap API key:\n", + "\n", + "1. Go to OpenWeatherMap and sign up for an API key [here](https://openweathermap.org/api/)\n", + "2. pip install pyowm\n", + "\n", + "Then we will need to set some environment variables:\n", + "1. Save your API KEY into OPENWEATHERMAP_API_KEY env variable\n", + "\n", + "## Use the wrapper" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "34bb5968", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.utilities import OpenWeatherMapAPIWrapper\n", + "import os\n", + "\n", + "os.environ[\"OPENWEATHERMAP_API_KEY\"] = \"\"\n", + "\n", + "weather = OpenWeatherMapAPIWrapper()" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "ac4910f8", + "metadata": {}, + "outputs": [ { - "cell_type": "code", - "execution_count": 37, - "id": "84b8f773", - "metadata": {}, - "outputs": [], - "source": [ - "weather = OpenWeatherMapAPIWrapper()" - ] - }, + "name": "stdout", + "output_type": "stream", + "text": [ + "In London,GB, the current weather is as follows:\n", + "Detailed status: broken clouds\n", + "Wind speed: 2.57 m/s, direction: 240°\n", + "Humidity: 55%\n", + "Temperature: \n", + " - Current: 20.12°C\n", + " - High: 21.75°C\n", + " - Low: 18.68°C\n", + " - Feels like: 19.62°C\n", + "Rain: {}\n", + "Heat index: None\n", + "Cloud cover: 75%\n" + ] + } + ], + "source": [ + "weather_data = weather.run(\"London,GB\")\n", + "print(weather_data)" + ] + }, + { + "cell_type": "markdown", + "id": "e73cfa56", + "metadata": {}, + "source": [ + "## Use the tool" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "b3367417", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.llms import OpenAI\n", + "from langchain.agents import load_tools, initialize_agent, AgentType\n", + "import os\n", + "\n", + "os.environ[\"OPENAI_API_KEY\"] = \"\"\n", + "os.environ[\"OPENWEATHERMAP_API_KEY\"] = \"\"\n", + "\n", + "llm = OpenAI(temperature=0)\n", + "\n", + "tools = load_tools([\"openweathermap-api\"], llm)\n", + "\n", + "agent_chain = initialize_agent(\n", + " tools=tools,\n", + " llm=llm,\n", + " agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,\n", + " verbose=True\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "bf4f6854", + "metadata": {}, + "outputs": [ { - "cell_type": "code", - "execution_count": 38, - "id": "9651f324-e74a-4f08-a28a-89db029f66f8", - "metadata": {}, - "outputs": [], - "source": [ - "weather_data = weather.run(\"London,GB\")" - ] + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "\n", + "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n", + "\u001b[32;1m\u001b[1;3m I need to find out the current weather in London.\n", + "Action: OpenWeatherMap\n", + "Action Input: London,GB\u001b[0m\n", + "Observation: \u001b[36;1m\u001b[1;3mIn London,GB, the current weather is as follows:\n", + "Detailed status: broken clouds\n", + "Wind speed: 2.57 m/s, direction: 240°\n", + "Humidity: 56%\n", + "Temperature: \n", + " - Current: 20.11°C\n", + " - High: 21.75°C\n", + " - Low: 18.68°C\n", + " - Feels like: 19.64°C\n", + "Rain: {}\n", + "Heat index: None\n", + "Cloud cover: 75%\u001b[0m\n", + "Thought:\u001b[32;1m\u001b[1;3m I now know the current weather in London.\n", + "Final Answer: The current weather in London is broken clouds, with a wind speed of 2.57 m/s, direction 240°, humidity of 56%, temperature of 20.11°C, high of 21.75°C, low of 18.68°C, and a heat index of None.\u001b[0m\n", + "\n", + "\u001b[1m> Finished chain.\u001b[0m\n" + ] }, { - "cell_type": "code", - "execution_count": 39, - "id": "028f4cba", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "In London,GB, the current weather is as follows:\n", - "Detailed status: overcast clouds\n", - "Wind speed: 4.63 m/s, direction: 150°\n", - "Humidity: 67%\n", - "Temperature: \n", - " - Current: 5.35°C\n", - " - High: 6.26°C\n", - " - Low: 3.49°C\n", - " - Feels like: 1.95°C\n", - "Rain: {}\n", - "Heat index: None\n", - "Cloud cover: 100%\n" - ] - } - ], - "source": [ - "print(weather_data)" + "data": { + "text/plain": [ + "'The current weather in London is broken clouds, with a wind speed of 2.57 m/s, direction 240°, humidity of 56%, temperature of 20.11°C, high of 21.75°C, low of 18.68°C, and a heat index of None.'" ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.2" - } + ], + "source": [ + "agent_chain.run(\"What's the weather like in London?\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" }, - "nbformat": 4, - "nbformat_minor": 5 + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.16" + } + }, + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/docs/modules/agents/tools/getting_started.md b/docs/modules/agents/tools/getting_started.md index 8e233536..0e496a40 100644 --- a/docs/modules/agents/tools/getting_started.md +++ b/docs/modules/agents/tools/getting_started.md @@ -156,7 +156,7 @@ Below is a list of all supported tools and relevant information: **openweathermap-api** - Tool Name: OpenWeatherMap -- Tool Description: A wrapper around OpenWeatherMap API. Useful for fetching current weather information for a specified location. Input should be a location string (e.g. 'London,GB'). +- Tool Description: A wrapper around OpenWeatherMap API. Useful for fetching current weather information for a specified location. Input should be a location string (e.g. London,GB). - Notes: A connection to the OpenWeatherMap API (https://api.openweathermap.org), specifically the `/data/2.5/weather` endpoint. - Requires LLM: No - Extra Parameters: `openweathermap_api_key` (your API key to access this endpoint) diff --git a/langchain/agents/load_tools.py b/langchain/agents/load_tools.py index 38865b08..507d78b4 100644 --- a/langchain/agents/load_tools.py +++ b/langchain/agents/load_tools.py @@ -34,6 +34,7 @@ from langchain.tools.searx_search.tool import SearxSearchResults, SearxSearchRun from langchain.tools.shell.tool import ShellTool from langchain.tools.wikipedia.tool import WikipediaQueryRun from langchain.tools.wolfram_alpha.tool import WolframAlphaQueryRun +from langchain.tools.openweathermap.tool import OpenWeatherMapQueryRun from langchain.utilities import ArxivAPIWrapper from langchain.utilities.bing_search import BingSearchAPIWrapper from langchain.utilities.duckduckgo_search import DuckDuckGoSearchAPIWrapper @@ -45,6 +46,7 @@ from langchain.utilities.searx_search import SearxSearchWrapper from langchain.utilities.serpapi import SerpAPIWrapper from langchain.utilities.wikipedia import WikipediaAPIWrapper from langchain.utilities.wolfram_alpha import WolframAlphaAPIWrapper +from langchain.utilities.openweathermap import OpenWeatherMapAPIWrapper def _get_python_repl() -> BaseTool: @@ -243,6 +245,10 @@ def _get_scenexplain(**kwargs: Any) -> BaseTool: return SceneXplainTool(**kwargs) +def _get_openweathermap(**kwargs: Any) -> BaseTool: + return OpenWeatherMapQueryRun(api_wrapper=OpenWeatherMapAPIWrapper(**kwargs)) + + _EXTRA_LLM_TOOLS: Dict[ str, Tuple[Callable[[Arg(BaseLanguageModel, "llm"), KwArg(Any)], BaseTool], List[str]], @@ -284,6 +290,7 @@ _EXTRA_OPTIONAL_TOOLS: Dict[str, Tuple[Callable[[KwArg(Any)], BaseTool], List[st ["awslambda_tool_name", "awslambda_tool_description", "function_name"], ), "sceneXplain": (_get_scenexplain, []), + "openweathermap-api": (_get_openweathermap, ["openweathermap_api_key"]), } diff --git a/langchain/tools/__init__.py b/langchain/tools/__init__.py index 91bfb957..a04272a4 100644 --- a/langchain/tools/__init__.py +++ b/langchain/tools/__init__.py @@ -25,6 +25,7 @@ from langchain.tools.ifttt import IFTTTWebhook from langchain.tools.metaphor_search import MetaphorSearchResults from langchain.tools.openapi.utils.api_models import APIOperation from langchain.tools.openapi.utils.openapi_utils import OpenAPISpec +from langchain.tools.openweathermap.tool import OpenWeatherMapQueryRun from langchain.tools.playwright import ( ClickTool, CurrentWebPageTool, @@ -84,6 +85,7 @@ __all__ = [ "NavigateBackTool", "NavigateTool", "OpenAPISpec", + "OpenWeatherMapQueryRun", "ReadFileTool", "SceneXplainTool", "ShellTool", diff --git a/langchain/tools/openweathermap/__init__.py b/langchain/tools/openweathermap/__init__.py index 9c9cff1a..3817cc87 100644 --- a/langchain/tools/openweathermap/__init__.py +++ b/langchain/tools/openweathermap/__init__.py @@ -1 +1,8 @@ """OpenWeatherMap API toolkit.""" + + +from langchain.tools.openweathermap.tool import OpenWeatherMapQueryRun + +__all__ = [ + "OpenWeatherMapQueryRun", +] diff --git a/langchain/tools/openweathermap/tool.py b/langchain/tools/openweathermap/tool.py index 5c2cb34e..03478e7b 100644 --- a/langchain/tools/openweathermap/tool.py +++ b/langchain/tools/openweathermap/tool.py @@ -1,5 +1,13 @@ """Tool for the OpenWeatherMap API.""" +from typing import Optional + +from pydantic import Field + +from langchain.callbacks.manager import ( + AsyncCallbackManagerForToolRun, + CallbackManagerForToolRun, +) from langchain.tools.base import BaseTool from langchain.utilities import OpenWeatherMapAPIWrapper @@ -7,23 +15,27 @@ from langchain.utilities import OpenWeatherMapAPIWrapper class OpenWeatherMapQueryRun(BaseTool): """Tool that adds the capability to query using the OpenWeatherMap API.""" - api_wrapper: OpenWeatherMapAPIWrapper + api_wrapper: OpenWeatherMapAPIWrapper = Field( + default_factory=OpenWeatherMapAPIWrapper + ) name = "OpenWeatherMap" description = ( "A wrapper around OpenWeatherMap API. " "Useful for fetching current weather information for a specified location. " - "Input should be a location string (e.g. 'London,GB')." + "Input should be a location string (e.g. London,GB)." ) - def __init__(self) -> None: - self.api_wrapper = OpenWeatherMapAPIWrapper() - return - - def _run(self, location: str) -> str: + def _run( + self, location: str, run_manager: Optional[CallbackManagerForToolRun] = None + ) -> str: """Use the OpenWeatherMap tool.""" return self.api_wrapper.run(location) - async def _arun(self, location: str) -> str: + async def _arun( + self, + location: str, + run_manager: Optional[AsyncCallbackManagerForToolRun] = None, + ) -> str: """Use the OpenWeatherMap tool asynchronously.""" raise NotImplementedError("OpenWeatherMapQueryRun does not support async") diff --git a/tests/unit_tests/tools/test_public_api.py b/tests/unit_tests/tools/test_public_api.py index f70ace64..189deda7 100644 --- a/tests/unit_tests/tools/test_public_api.py +++ b/tests/unit_tests/tools/test_public_api.py @@ -37,6 +37,7 @@ _EXPECTED = [ "NavigateBackTool", "NavigateTool", "OpenAPISpec", + "OpenWeatherMapQueryRun", "ReadFileTool", "SceneXplainTool", "ShellTool",