forked from Archives/langchain
parent
f16c1fb6df
commit
aff33d52c5
128
docs/modules/agents/tools/examples/openweathermap.ipynb
Normal file
128
docs/modules/agents/tools/examples/openweathermap.ipynb
Normal file
@ -0,0 +1,128 @@
|
||||
{
|
||||
"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"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 37,
|
||||
"id": "84b8f773",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"weather = OpenWeatherMapAPIWrapper()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 38,
|
||||
"id": "9651f324-e74a-4f08-a28a-89db029f66f8",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"weather_data = weather.run(\"London,GB\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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)"
|
||||
]
|
||||
}
|
||||
],
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
@ -152,3 +152,11 @@ Below is a list of all supported tools and relevant information:
|
||||
- Notes: A natural language connection to the Listen Notes Podcast API (`https://www.PodcastAPI.com`), specifically the `/search/` endpoint.
|
||||
- Requires LLM: Yes
|
||||
- Extra Parameters: `listen_api_key` (your api key to access this endpoint)
|
||||
|
||||
**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').
|
||||
- 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)
|
||||
|
1
langchain/tools/openweathermap/__init__.py
Normal file
1
langchain/tools/openweathermap/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
"""OpenWeatherMap API toolkit."""
|
29
langchain/tools/openweathermap/tool.py
Normal file
29
langchain/tools/openweathermap/tool.py
Normal file
@ -0,0 +1,29 @@
|
||||
"""Tool for the OpenWeatherMap API."""
|
||||
|
||||
from langchain.tools.base import BaseTool
|
||||
from langchain.utilities import OpenWeatherMapAPIWrapper
|
||||
|
||||
|
||||
class OpenWeatherMapQueryRun(BaseTool):
|
||||
"""Tool that adds the capability to query using the OpenWeatherMap API."""
|
||||
|
||||
api_wrapper: 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')."
|
||||
)
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.api_wrapper = OpenWeatherMapAPIWrapper()
|
||||
return
|
||||
|
||||
def _run(self, location: str) -> str:
|
||||
"""Use the OpenWeatherMap tool."""
|
||||
return self.api_wrapper.run(location)
|
||||
|
||||
async def _arun(self, location: str) -> str:
|
||||
"""Use the OpenWeatherMap tool asynchronously."""
|
||||
raise NotImplementedError("OpenWeatherMapQueryRun does not support async")
|
@ -5,6 +5,7 @@ from langchain.utilities.bash import BashProcess
|
||||
from langchain.utilities.bing_search import BingSearchAPIWrapper
|
||||
from langchain.utilities.google_search import GoogleSearchAPIWrapper
|
||||
from langchain.utilities.google_serper import GoogleSerperAPIWrapper
|
||||
from langchain.utilities.openweathermap import OpenWeatherMapAPIWrapper
|
||||
from langchain.utilities.searx_search import SearxSearchWrapper
|
||||
from langchain.utilities.serpapi import SerpAPIWrapper
|
||||
from langchain.utilities.wikipedia import WikipediaAPIWrapper
|
||||
@ -21,4 +22,5 @@ __all__ = [
|
||||
"SearxSearchWrapper",
|
||||
"BingSearchAPIWrapper",
|
||||
"WikipediaAPIWrapper",
|
||||
"OpenWeatherMapAPIWrapper",
|
||||
]
|
||||
|
79
langchain/utilities/openweathermap.py
Normal file
79
langchain/utilities/openweathermap.py
Normal file
@ -0,0 +1,79 @@
|
||||
"""Util that calls OpenWeatherMap using PyOWM."""
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
from pydantic import Extra, root_validator
|
||||
|
||||
from langchain.tools.base import BaseModel
|
||||
from langchain.utils import get_from_dict_or_env
|
||||
|
||||
|
||||
class OpenWeatherMapAPIWrapper(BaseModel):
|
||||
"""Wrapper for OpenWeatherMap API using PyOWM.
|
||||
|
||||
Docs for using:
|
||||
|
||||
1. Go to OpenWeatherMap and sign up for an API key
|
||||
3. Save your API KEY into OPENWEATHERMAP_API_KEY env variable
|
||||
4. pip install wolframalpha
|
||||
"""
|
||||
|
||||
owm: Any
|
||||
openweathermap_api_key: Optional[str] = None
|
||||
|
||||
class Config:
|
||||
"""Configuration for this pydantic object."""
|
||||
|
||||
extra = Extra.forbid
|
||||
|
||||
@root_validator(pre=True)
|
||||
def validate_environment(cls, values: Dict) -> Dict:
|
||||
"""Validate that api key exists in environment."""
|
||||
openweathermap_api_key = get_from_dict_or_env(
|
||||
values, "openweathermap_api_key", "OPENWEATHERMAP_API_KEY"
|
||||
)
|
||||
values["openweathermap_api_key"] = openweathermap_api_key
|
||||
|
||||
try:
|
||||
import pyowm
|
||||
|
||||
except ImportError:
|
||||
raise ImportError(
|
||||
"pyowm is not installed. " "Please install it with `pip install pyowm`"
|
||||
)
|
||||
|
||||
owm = pyowm.OWM(openweathermap_api_key)
|
||||
values["owm"] = owm
|
||||
|
||||
return values
|
||||
|
||||
def _format_weather_info(self, location: str, w: Any) -> str:
|
||||
detailed_status = w.detailed_status
|
||||
wind = w.wind()
|
||||
humidity = w.humidity
|
||||
temperature = w.temperature("celsius")
|
||||
rain = w.rain
|
||||
heat_index = w.heat_index
|
||||
clouds = w.clouds
|
||||
|
||||
return (
|
||||
f"In {location}, the current weather is as follows:\n"
|
||||
f"Detailed status: {detailed_status}\n"
|
||||
f"Wind speed: {wind['speed']} m/s, direction: {wind['deg']}°\n"
|
||||
f"Humidity: {humidity}%\n"
|
||||
f"Temperature: \n"
|
||||
f" - Current: {temperature['temp']}°C\n"
|
||||
f" - High: {temperature['temp_max']}°C\n"
|
||||
f" - Low: {temperature['temp_min']}°C\n"
|
||||
f" - Feels like: {temperature['feels_like']}°C\n"
|
||||
f"Rain: {rain}\n"
|
||||
f"Heat index: {heat_index}\n"
|
||||
f"Cloud cover: {clouds}%"
|
||||
)
|
||||
|
||||
def run(self, location: str) -> str:
|
||||
"""Get the current weather information for a specified location."""
|
||||
mgr = self.owm.weather_manager()
|
||||
observation = mgr.weather_at_place(location)
|
||||
w = observation.weather
|
||||
|
||||
return self._format_weather_info(location, w)
|
56
poetry.lock
generated
56
poetry.lock
generated
@ -1,4 +1,4 @@
|
||||
# This file is automatically @generated by Poetry and should not be changed by hand.
|
||||
# This file is automatically @generated by Poetry 1.4.1 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "absl-py"
|
||||
@ -1779,6 +1779,18 @@ files = [
|
||||
{file = "gast-0.4.0.tar.gz", hash = "sha256:40feb7b8b8434785585ab224d1568b857edb18297e5a3047f1ba012bc83b42c1"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "geojson"
|
||||
version = "2.5.0"
|
||||
description = "Python bindings and utilities for GeoJSON"
|
||||
category = "main"
|
||||
optional = true
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "geojson-2.5.0-py2.py3-none-any.whl", hash = "sha256:ccbd13368dd728f4e4f13ffe6aaf725b6e802c692ba0dde628be475040c534ba"},
|
||||
{file = "geojson-2.5.0.tar.gz", hash = "sha256:6e4bb7ace4226a45d9c8c8b1348b3fc43540658359f93c3f7e03efa9f15f658a"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "google-api-core"
|
||||
version = "2.11.0"
|
||||
@ -5359,6 +5371,26 @@ dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pyte
|
||||
docs = ["sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"]
|
||||
tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "pyowm"
|
||||
version = "3.3.0"
|
||||
description = "A Python wrapper around OpenWeatherMap web APIs"
|
||||
category = "main"
|
||||
optional = true
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "pyowm-3.3.0-py3-none-any.whl", hash = "sha256:86463108e7613171531ba306040b43c972b3fc0b0acf73b12c50910cdd2107ab"},
|
||||
{file = "pyowm-3.3.0.tar.gz", hash = "sha256:8196f77c91eac680676ed5ee484aae8a165408055e3e2b28025cbf60b8681e03"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
geojson = ">=2.3.0,<3"
|
||||
PySocks = ">=1.7.1,<2"
|
||||
requests = [
|
||||
{version = ">=2.20.0,<3"},
|
||||
{version = "*", extras = ["socks"]},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyparsing"
|
||||
version = "3.0.9"
|
||||
@ -5433,6 +5465,19 @@ files = [
|
||||
{file = "pyrsistent-0.19.3.tar.gz", hash = "sha256:1a2994773706bbb4995c31a97bc94f1418314923bd1048c6d964837040376440"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pysocks"
|
||||
version = "1.7.1"
|
||||
description = "A Python SOCKS client module. See https://github.com/Anorov/PySocks for more information."
|
||||
category = "main"
|
||||
optional = true
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
files = [
|
||||
{file = "PySocks-1.7.1-py27-none-any.whl", hash = "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299"},
|
||||
{file = "PySocks-1.7.1-py3-none-any.whl", hash = "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5"},
|
||||
{file = "PySocks-1.7.1.tar.gz", hash = "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytest"
|
||||
version = "7.2.2"
|
||||
@ -5968,6 +6013,7 @@ files = [
|
||||
certifi = ">=2017.4.17"
|
||||
charset-normalizer = ">=2,<4"
|
||||
idna = ">=2.5,<4"
|
||||
PySocks = {version = ">=1.5.6,<1.5.7 || >1.5.7", optional = true, markers = "extra == \"socks\""}
|
||||
urllib3 = ">=1.21.1,<1.27"
|
||||
|
||||
[package.extras]
|
||||
@ -6822,7 +6868,7 @@ files = [
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
greenlet = {version = "!=0.4.17", markers = "python_version >= \"3\" and (platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\")"}
|
||||
greenlet = {version = "!=0.4.17", markers = "python_version >= \"3\" and platform_machine == \"aarch64\" or python_version >= \"3\" and platform_machine == \"ppc64le\" or python_version >= \"3\" and platform_machine == \"x86_64\" or python_version >= \"3\" and platform_machine == \"amd64\" or python_version >= \"3\" and platform_machine == \"AMD64\" or python_version >= \"3\" and platform_machine == \"win32\" or python_version >= \"3\" and platform_machine == \"WIN32\""}
|
||||
|
||||
[package.extras]
|
||||
aiomysql = ["aiomysql", "greenlet (!=0.4.17)"]
|
||||
@ -8482,10 +8528,10 @@ docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker
|
||||
testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"]
|
||||
|
||||
[extras]
|
||||
all = ["anthropic", "cohere", "openai", "nlpcloud", "huggingface_hub", "jina", "manifest-ml", "elasticsearch", "opensearch-py", "google-search-results", "faiss-cpu", "sentence-transformers", "transformers", "spacy", "nltk", "wikipedia", "beautifulsoup4", "tiktoken", "torch", "jinja2", "pinecone-client", "weaviate-client", "redis", "google-api-python-client", "wolframalpha", "qdrant-client", "tensorflow-text", "pypdf", "networkx", "nomic", "aleph-alpha-client", "deeplake", "pgvector", "psycopg2-binary"]
|
||||
llms = ["anthropic", "cohere", "openai", "nlpcloud", "huggingface_hub", "manifest-ml", "torch", "transformers"]
|
||||
all = ["aleph-alpha-client", "anthropic", "beautifulsoup4", "cohere", "deeplake", "elasticsearch", "faiss-cpu", "google-api-python-client", "google-search-results", "huggingface_hub", "jina", "jinja2", "manifest-ml", "networkx", "nlpcloud", "nltk", "nomic", "openai", "opensearch-py", "pgvector", "pinecone-client", "psycopg2-binary", "pypdf", "qdrant-client", "redis", "sentence-transformers", "spacy", "tensorflow-text", "tiktoken", "torch", "transformers", "weaviate-client", "wikipedia", "wolframalpha"]
|
||||
llms = ["anthropic", "cohere", "huggingface_hub", "manifest-ml", "nlpcloud", "openai", "torch", "transformers"]
|
||||
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = ">=3.8.1,<4.0"
|
||||
content-hash = "4986fe2bbc54d9c31181a843f7b3e0a9b1b46ad833fc24e52f1c181fe2ba54f5"
|
||||
content-hash = "fec488d52fc1a46ae34a643e5951e00251232d6d38c50c844556041df6067572"
|
||||
|
@ -54,7 +54,7 @@ aleph-alpha-client = {version="^2.15.0", optional = true}
|
||||
deeplake = {version = "^3.2.9", optional = true}
|
||||
pgvector = {version = "^0.1.6", optional = true}
|
||||
psycopg2-binary = {version = "^2.9.5", optional = true}
|
||||
|
||||
pyowm = {version = "^3.3.0", optional = true}
|
||||
|
||||
[tool.poetry.group.docs.dependencies]
|
||||
autodoc_pydantic = "^1.8.0"
|
||||
|
24
tests/integration_tests/test_openweathermap.py
Normal file
24
tests/integration_tests/test_openweathermap.py
Normal file
@ -0,0 +1,24 @@
|
||||
from langchain.utilities.openweathermap import OpenWeatherMapAPIWrapper
|
||||
|
||||
|
||||
def test_openweathermap_api_wrapper() -> None:
|
||||
"""Test that OpenWeatherMapAPIWrapper returns correct data for London, GB."""
|
||||
|
||||
weather = OpenWeatherMapAPIWrapper()
|
||||
weather_data = weather.run("London,GB")
|
||||
|
||||
assert weather_data is not None
|
||||
assert "London" in weather_data
|
||||
assert "GB" in weather_data
|
||||
assert "Detailed status:" in weather_data
|
||||
assert "Wind speed:" in weather_data
|
||||
assert "direction:" in weather_data
|
||||
assert "Humidity:" in weather_data
|
||||
assert "Temperature:" in weather_data
|
||||
assert "Current:" in weather_data
|
||||
assert "High:" in weather_data
|
||||
assert "Low:" in weather_data
|
||||
assert "Feels like:" in weather_data
|
||||
assert "Rain:" in weather_data
|
||||
assert "Heat index:" in weather_data
|
||||
assert "Cloud cover:" in weather_data
|
Loading…
Reference in New Issue
Block a user