ai-parrot 0.3.4__cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ai-parrot might be problematic. Click here for more details.

Files changed (109) hide show
  1. ai_parrot-0.3.4.dist-info/LICENSE +21 -0
  2. ai_parrot-0.3.4.dist-info/METADATA +319 -0
  3. ai_parrot-0.3.4.dist-info/RECORD +109 -0
  4. ai_parrot-0.3.4.dist-info/WHEEL +6 -0
  5. ai_parrot-0.3.4.dist-info/top_level.txt +3 -0
  6. parrot/__init__.py +21 -0
  7. parrot/chatbots/__init__.py +7 -0
  8. parrot/chatbots/abstract.py +728 -0
  9. parrot/chatbots/asktroc.py +16 -0
  10. parrot/chatbots/base.py +366 -0
  11. parrot/chatbots/basic.py +9 -0
  12. parrot/chatbots/bose.py +17 -0
  13. parrot/chatbots/cody.py +17 -0
  14. parrot/chatbots/copilot.py +83 -0
  15. parrot/chatbots/dataframe.py +103 -0
  16. parrot/chatbots/hragents.py +15 -0
  17. parrot/chatbots/odoo.py +17 -0
  18. parrot/chatbots/retrievals/__init__.py +578 -0
  19. parrot/chatbots/retrievals/constitutional.py +19 -0
  20. parrot/conf.py +110 -0
  21. parrot/crew/__init__.py +3 -0
  22. parrot/crew/tools/__init__.py +22 -0
  23. parrot/crew/tools/bing.py +13 -0
  24. parrot/crew/tools/config.py +43 -0
  25. parrot/crew/tools/duckgo.py +62 -0
  26. parrot/crew/tools/file.py +24 -0
  27. parrot/crew/tools/google.py +168 -0
  28. parrot/crew/tools/gtrends.py +16 -0
  29. parrot/crew/tools/md2pdf.py +25 -0
  30. parrot/crew/tools/rag.py +42 -0
  31. parrot/crew/tools/search.py +32 -0
  32. parrot/crew/tools/url.py +21 -0
  33. parrot/exceptions.cpython-311-x86_64-linux-gnu.so +0 -0
  34. parrot/handlers/__init__.py +4 -0
  35. parrot/handlers/bots.py +196 -0
  36. parrot/handlers/chat.py +162 -0
  37. parrot/interfaces/__init__.py +6 -0
  38. parrot/interfaces/database.py +29 -0
  39. parrot/llms/__init__.py +137 -0
  40. parrot/llms/abstract.py +47 -0
  41. parrot/llms/anthropic.py +42 -0
  42. parrot/llms/google.py +42 -0
  43. parrot/llms/groq.py +45 -0
  44. parrot/llms/hf.py +45 -0
  45. parrot/llms/openai.py +59 -0
  46. parrot/llms/pipes.py +114 -0
  47. parrot/llms/vertex.py +78 -0
  48. parrot/loaders/__init__.py +20 -0
  49. parrot/loaders/abstract.py +456 -0
  50. parrot/loaders/audio.py +106 -0
  51. parrot/loaders/basepdf.py +102 -0
  52. parrot/loaders/basevideo.py +280 -0
  53. parrot/loaders/csv.py +42 -0
  54. parrot/loaders/dir.py +37 -0
  55. parrot/loaders/excel.py +349 -0
  56. parrot/loaders/github.py +65 -0
  57. parrot/loaders/handlers/__init__.py +5 -0
  58. parrot/loaders/handlers/data.py +213 -0
  59. parrot/loaders/image.py +119 -0
  60. parrot/loaders/json.py +52 -0
  61. parrot/loaders/pdf.py +437 -0
  62. parrot/loaders/pdfchapters.py +142 -0
  63. parrot/loaders/pdffn.py +112 -0
  64. parrot/loaders/pdfimages.py +207 -0
  65. parrot/loaders/pdfmark.py +88 -0
  66. parrot/loaders/pdftables.py +145 -0
  67. parrot/loaders/ppt.py +30 -0
  68. parrot/loaders/qa.py +81 -0
  69. parrot/loaders/repo.py +103 -0
  70. parrot/loaders/rtd.py +65 -0
  71. parrot/loaders/txt.py +92 -0
  72. parrot/loaders/utils/__init__.py +1 -0
  73. parrot/loaders/utils/models.py +25 -0
  74. parrot/loaders/video.py +96 -0
  75. parrot/loaders/videolocal.py +120 -0
  76. parrot/loaders/vimeo.py +106 -0
  77. parrot/loaders/web.py +216 -0
  78. parrot/loaders/web_base.py +112 -0
  79. parrot/loaders/word.py +125 -0
  80. parrot/loaders/youtube.py +192 -0
  81. parrot/manager.py +166 -0
  82. parrot/models.py +372 -0
  83. parrot/py.typed +0 -0
  84. parrot/stores/__init__.py +48 -0
  85. parrot/stores/abstract.py +171 -0
  86. parrot/stores/milvus.py +632 -0
  87. parrot/stores/qdrant.py +153 -0
  88. parrot/tools/__init__.py +12 -0
  89. parrot/tools/abstract.py +53 -0
  90. parrot/tools/asknews.py +32 -0
  91. parrot/tools/bing.py +13 -0
  92. parrot/tools/duck.py +62 -0
  93. parrot/tools/google.py +170 -0
  94. parrot/tools/stack.py +26 -0
  95. parrot/tools/weather.py +70 -0
  96. parrot/tools/wikipedia.py +59 -0
  97. parrot/tools/zipcode.py +179 -0
  98. parrot/utils/__init__.py +2 -0
  99. parrot/utils/parsers/__init__.py +5 -0
  100. parrot/utils/parsers/toml.cpython-311-x86_64-linux-gnu.so +0 -0
  101. parrot/utils/toml.py +11 -0
  102. parrot/utils/types.cpython-311-x86_64-linux-gnu.so +0 -0
  103. parrot/utils/uv.py +11 -0
  104. parrot/version.py +10 -0
  105. resources/users/__init__.py +5 -0
  106. resources/users/handlers.py +13 -0
  107. resources/users/models.py +205 -0
  108. settings/__init__.py +0 -0
  109. settings/settings.py +51 -0
@@ -0,0 +1,153 @@
1
+ from typing import Any
2
+ from qdrant_client import QdrantClient # pylint: disable=import-error
3
+ from langchain_community.vectorstores import ( # pylint: disable=import-error, E0611
4
+ Qdrant
5
+ )
6
+ from .abstract import AbstractStore
7
+ from ..conf import (
8
+ QDRANT_PROTOCOL,
9
+ QDRANT_HOST,
10
+ QDRANT_PORT,
11
+ QDRANT_USE_HTTPS,
12
+ QDRANT_CONN_TYPE,
13
+ QDRANT_URL
14
+ )
15
+
16
+
17
+ class QdrantStore(AbstractStore):
18
+ """QdrantStore class.
19
+
20
+
21
+ Args:
22
+ host (str): Qdrant host.
23
+ port (int): Qdrant port.
24
+ index_name (str): Qdrant index name.
25
+ """
26
+
27
+ def _create_qdrant_client(self, host, port, url, https, verify, qdrant_args):
28
+ """
29
+ Creates a Qdrant client based on the provided configuration.
30
+
31
+ Args:
32
+ host: Host of the Qdrant server (if using "server" connection).
33
+ port: Port of the Qdrant server (if using "server" connection).
34
+ url: URL of the Qdrant cloud service (if using "cloud" connection).
35
+ https: Whether to use HTTPS for the connection.
36
+ verify: Whether to verify the SSL certificate.
37
+ qdrant_args: Additional arguments for the Qdrant client.
38
+
39
+ Returns:
40
+ A QdrantClient object.
41
+ """
42
+ if url is not None:
43
+ return QdrantClient(
44
+ url=url,
45
+ port=None,
46
+ verify=verify,
47
+ **qdrant_args
48
+ )
49
+ else:
50
+ return QdrantClient(
51
+ host,
52
+ port=port,
53
+ https=https,
54
+ verify=verify,
55
+ **qdrant_args
56
+ )
57
+
58
+ def __init__(self, embeddings = None, **kwargs):
59
+ super().__init__(embeddings, **kwargs)
60
+ self.host = kwargs.get("host", QDRANT_HOST)
61
+ self.port = kwargs.get("port", QDRANT_PORT)
62
+ qdrant_args = kwargs.get("qdrant_args", {})
63
+ connection_type = kwargs.get("connection_type", QDRANT_CONN_TYPE)
64
+ url = kwargs.get("url", QDRANT_URL)
65
+ if connection_type == "server":
66
+ self.client = self._create_qdrant_client(
67
+ self.host, self.port, url, QDRANT_USE_HTTPS, False, qdrant_args
68
+ )
69
+ elif connection_type == "cloud":
70
+ if url is None:
71
+ raise ValueError(
72
+ "A URL is required for 'cloud' connection"
73
+ )
74
+ self.client = self._create_qdrant_client(
75
+ None, None, url, False, False, qdrant_args
76
+ )
77
+ else:
78
+ raise ValueError(
79
+ f"Invalid connection type: {connection_type}"
80
+ )
81
+ if url is not None:
82
+ self.url = url
83
+ else:
84
+ self.url = f"{QDRANT_PROTOCOL}://{self.host}"
85
+ if self.port:
86
+ self.url += f":{self.port}"
87
+
88
+ def get_vectorstore(self):
89
+ if self._embed_ is None:
90
+ _embed_ = self.create_embedding(
91
+ model_name=self.embedding_name
92
+ )
93
+ else:
94
+ _embed_ = self._embed_
95
+ self.vector = Qdrant(
96
+ client=self.client,
97
+ collection_name=self.collection,
98
+ embeddings=_embed_,
99
+ )
100
+ return self.vector
101
+
102
+ async def load_documents(
103
+ self,
104
+ documents: list,
105
+ collection: str = None
106
+ ):
107
+ if collection is None:
108
+ collection = self.collection
109
+
110
+ docstore = Qdrant.from_documents(
111
+ documents,
112
+ self._embed_,
113
+ url=self.url,
114
+ # location=":memory:", # Local mode with in-memory storage only
115
+ collection_name=collection,
116
+ force_recreate=False,
117
+ )
118
+ return docstore
119
+
120
+ def upsert(self, payload: dict, collection: str = None) -> None:
121
+ if collection is None:
122
+ collection = self.collection
123
+ self.client.upsert(
124
+ collection_name=collection,
125
+ points=self._embed_,
126
+ payload=payload
127
+ )
128
+
129
+ def search(self, payload: dict, collection: str = None) -> dict:
130
+ pass
131
+
132
+ async def delete_collection(self, collection: str = None) -> dict:
133
+ self.client.delete_collection(
134
+ collection_name=collection
135
+ )
136
+
137
+ async def create_collection(
138
+ self,
139
+ collection_name: str,
140
+ document: Any,
141
+ dimension: int = 768,
142
+ **kwargs
143
+ ) -> dict:
144
+ # Here using drop_old=True to force recreate based on the first document
145
+ docstore = Qdrant.from_documents(
146
+ [document],
147
+ self._embed_,
148
+ url=self.url,
149
+ # location=":memory:", # Local mode with in-memory storage only
150
+ collection_name=collection_name,
151
+ force_recreate=True,
152
+ )
153
+ return docstore
@@ -0,0 +1,12 @@
1
+ from langchain_community.tools.yahoo_finance_news import YahooFinanceNewsTool
2
+ from langchain_community.tools import YouTubeSearchTool
3
+ from langchain_community.agent_toolkits import O365Toolkit
4
+ from navconfig import config
5
+ from .wikipedia import WikipediaTool, WikidataTool
6
+ from .asknews import AskNewsTool
7
+ from .duck import DuckDuckGoSearchTool, DuckDuckGoRelevantSearch
8
+ from .weather import OpenWeather, OpenWeatherMapTool
9
+ from .google import GoogleLocationFinder, GoogleSiteSearchTool, GoogleSearchTool
10
+ from .zipcode import ZipcodeAPIToolkit
11
+ from .bing import BingSearchTool
12
+ from .stack import StackExchangeTool
@@ -0,0 +1,53 @@
1
+ from typing import Optional, Dict, Any, Type
2
+ from abc import abstractmethod
3
+ from langchain_core.pydantic_v1 import BaseModel, Field, Extra
4
+ from langchain_core.callbacks import CallbackManagerForToolRun
5
+ from langchain_core.tools import BaseTool
6
+
7
+ class AbstractToolArgsSchema(BaseModel):
8
+ """Schema for the arguments to the AbstractTool."""
9
+
10
+ # This Field allows any number of arguments to be passed in.
11
+ args: list = Field(description="A list of arguments to the tool")
12
+
13
+
14
+ class AbstractTool(BaseTool):
15
+ """Abstract class for tools."""
16
+
17
+ args_schema: Type[BaseModel] = AbstractToolArgsSchema
18
+
19
+ class Config:
20
+ """Configuration for this pydantic object."""
21
+ extra = Extra.forbid
22
+ arbitrary_types_allowed = True
23
+
24
+ @abstractmethod
25
+ def _search(self, query: str) -> str:
26
+ """Run the tool."""
27
+
28
+ async def _asearch(self, *args, **kwargs):
29
+ """Run the tool asynchronously."""
30
+ return self._search(*args, **kwargs)
31
+
32
+ def _run(
33
+ self,
34
+ query: str,
35
+ run_manager: Optional[CallbackManagerForToolRun] = None
36
+ ) -> Dict[str, Any]:
37
+ args = [a.strip() for a in query.split(',')]
38
+ try:
39
+ return self._search(*args)
40
+ except Exception as e:
41
+ raise ValueError(f"Error running tool: {e}") from e
42
+
43
+ async def _arun(
44
+ self,
45
+ query: str,
46
+ run_manager: Optional[CallbackManagerForToolRun] = None
47
+ ) -> Dict[str, Any]:
48
+ """Use the tool asynchronously."""
49
+ args = [a.strip() for a in query.split(',')]
50
+ try:
51
+ return await self._asearch(*args)
52
+ except Exception as e:
53
+ raise ValueError(f"Error running tool: {e}") from e
@@ -0,0 +1,32 @@
1
+ from typing import Any
2
+ import os
3
+ from navconfig import config
4
+ from langchain_community.tools.asknews import AskNewsSearch
5
+ from langchain.tools import BaseTool
6
+
7
+ class AskNewsTool(BaseTool):
8
+ """Tool that searches the AskNews API."""
9
+ name: str = "asknews_search"
10
+ description: str = (
11
+ "This tool allows you to perform a search on up-to-date news and historical "
12
+ "news. If you needs news from more than 48 hours ago, you can estimate the "
13
+ "number of hours back to search."
14
+ )
15
+ search: Any = None
16
+
17
+ def __init__(self, max_results: int = 5, **kwargs):
18
+ super().__init__(**kwargs)
19
+ os.environ["ASKNEWS_CLIENT_ID"] = config.get('ASKNEWS_CLIENT_ID')
20
+ os.environ["ASKNEWS_CLIENT_SECRET"] = config.get('ASKNEWS_CLIENT_SECRET')
21
+ self.search = AskNewsSearch(max_results=5)
22
+
23
+ def _run(
24
+ self,
25
+ query: str
26
+ ) -> str:
27
+ """Use the Wikipedia tool."""
28
+ return self.search.invoke(
29
+ {
30
+ "query": query,
31
+ }
32
+ )
parrot/tools/bing.py ADDED
@@ -0,0 +1,13 @@
1
+ from langchain_community.utilities.bing_search import BingSearchAPIWrapper
2
+ from langchain.tools import BaseTool
3
+
4
+
5
+ class BingSearchTool(BaseTool):
6
+ """Microsoft Bing Search Tool."""
7
+ name: str = "Bing Search"
8
+ description: str = "Search the web using Microsoft Bing Search API"
9
+
10
+ def _run(self, query: str) -> dict:
11
+ """Run the Bing Search Tool."""
12
+ bing = BingSearchAPIWrapper(k=5)
13
+ return bing.results(query=query, num_results=5)
parrot/tools/duck.py ADDED
@@ -0,0 +1,62 @@
1
+ from typing import Any
2
+ from pydantic import PrivateAttr
3
+ from langchain_community.tools.ddg_search.tool import (
4
+ DuckDuckGoSearchResults,
5
+ DuckDuckGoSearchAPIWrapper
6
+ )
7
+ from duckduckgo_search import DDGS
8
+ from langchain.tools import BaseTool
9
+
10
+
11
+ class DuckDuckGoSearchTool(BaseTool):
12
+ """Web Search tool using Duck Duck Go API."""
13
+ name: str = "DuckDuckGo Web Search"
14
+ description: str = "Search the web using DuckDuckGo Search API"
15
+ source: Any = None
16
+ max_results: int = 5
17
+ region: str = None
18
+
19
+ def __init__(self, source: str = "news", results: int = 5, region: str = 'wt-wt', **kwargs: Any):
20
+ super().__init__(**kwargs)
21
+ self.source = source
22
+ self.max_results = results
23
+ self.region = region
24
+
25
+ def _run(self, query: str) -> dict:
26
+ """Run the DuckDuckGo Search Tool."""
27
+ wrapper = DuckDuckGoSearchAPIWrapper(
28
+ region=self.region,
29
+ time="y",
30
+ max_results=self.max_results
31
+ )
32
+ search = DuckDuckGoSearchResults(
33
+ api_wrapper=wrapper,
34
+ source=self.source
35
+ )
36
+ return search.run(query)
37
+
38
+ class DuckDuckGoRelevantSearch(BaseTool):
39
+ """Web Search tool using Duck Duck Go API."""
40
+ name: str = "DuckDuckGo Relevant Search"
41
+ description: str = "Search the web using DuckDuckGo Search API"
42
+ _max_results: PrivateAttr
43
+ _region: PrivateAttr
44
+
45
+ def __init__(self, results: int = 5, region: str = 'wt-wt', **kwargs: Any):
46
+ super().__init__(**kwargs)
47
+ self._max_results = results
48
+ self._region = region
49
+
50
+ def _run(
51
+ self,
52
+ query: str,
53
+ **kwargs: Any,
54
+ ) -> Any:
55
+ """Search Internet for relevant information based on a query."""
56
+ search = DDGS()
57
+ return search.text(
58
+ keywords=query,
59
+ region=self._region,
60
+ safesearch='moderate',
61
+ max_results=self._max_results
62
+ )
parrot/tools/google.py ADDED
@@ -0,0 +1,170 @@
1
+ from typing import Optional
2
+ import requests
3
+ from googleapiclient.discovery import build
4
+ from pydantic import PrivateAttr
5
+ # from crewai_tools import BaseTool
6
+ from langchain.tools import BaseTool
7
+ from navconfig import config
8
+ from ..conf import GOOGLE_API_KEY
9
+
10
+
11
+ class GoogleSearchTool(BaseTool):
12
+ """Web Search tool using Google API."""
13
+ name: str = "Google Web Search"
14
+ description: str = (
15
+ "Search the web using Google Search API, useful when you need to answer questions about current events.",
16
+ " Use this tool more than the Wikipedia tool if you are asked about current events, recent information, or news"
17
+ )
18
+ source: str = 'news'
19
+ max_results: int = 5
20
+ region: str = 'US'
21
+ # Fields populated during init (not required for validation)
22
+ cse_id: Optional[str] = None
23
+ search_key: Optional[str] = None
24
+ kwargs: Optional[dict] = None
25
+
26
+ def __init__(self, source: str = "news", results: int = 5, **kwargs):
27
+ super().__init__(**kwargs)
28
+ self.source = source
29
+ self.max_results = results
30
+ self.cse_id = config.get('GOOGLE_SEARCH_ENGINE_ID')
31
+ self.search_key = config.get('GOOGLE_SEARCH_API_KEY')
32
+ self.kwargs = kwargs
33
+
34
+ def _run(self, query: str) -> list:
35
+ """Run the Google Search Tool."""
36
+ service = build("customsearch", "v1", developerKey=self.search_key)
37
+ res = service.cse().list( # pylint: disable=no-member
38
+ q=query,
39
+ cx=self.cse_id,
40
+ num=self.max_results,
41
+ **self.kwargs
42
+ ).execute()
43
+ results = []
44
+ for item in res['items']:
45
+ results.append(
46
+ {
47
+ 'snippet': item['snippet'],
48
+ 'title': item['title'],
49
+ 'link': item['link'],
50
+ 'description': item['snippet']
51
+ }
52
+ )
53
+ return results
54
+
55
+
56
+ class GoogleSiteSearchTool(BaseTool):
57
+ """Web Search under a site using Google API."""
58
+ name: str = "Google Web Search"
59
+ description: str = "Search the web using Google Search API"
60
+ source: str = 'news'
61
+ max_results: int = 5
62
+ region: str = ''
63
+
64
+ def __init__(self, site: str = "news", results: int = 5, **kwargs):
65
+ super().__init__(**kwargs)
66
+ self.source = site
67
+ self.max_results = results
68
+ self._cse_id = config.get('GOOGLE_SEARCH_ENGINE_ID')
69
+ self._search_key = config.get('GOOGLE_SEARCH_API_KEY')
70
+ self._kwargs = kwargs
71
+
72
+ def _run(self, query: str) -> dict:
73
+ """Run the Google Search Tool."""
74
+ service = build("customsearch", "v1", developerKey=self._search_key)
75
+ qs = f'{query} site:{self.source}'
76
+ res = service.cse().list( # pylint: disable=no-member
77
+ q=qs,
78
+ cx=self._cse_id,
79
+ num=self.max_results,
80
+ **self._kwargs
81
+ ).execute()
82
+ results = []
83
+ for item in res['items']:
84
+ results.append(
85
+ {
86
+ 'snippet': item['snippet'],
87
+ 'title': item['title'],
88
+ 'link': item['link'],
89
+ 'description': item['snippet']
90
+ }
91
+ )
92
+ return results
93
+
94
+
95
+ class GoogleLocationFinder(BaseTool):
96
+ """ LocationFinder class for finding locations."""
97
+ name: str = "google_maps_location_finder"
98
+ description: str = (
99
+ "Search for location information, use this tool to find latitude, longitude and other geographical information from locations."
100
+ " Provide the complete address to this tool to receive location information"
101
+ )
102
+ google_key: str = None
103
+ base_url: str = "https://maps.googleapis.com/maps/api/geocode/json"
104
+ kwargs: Optional[dict] = None
105
+
106
+ def __init__(self, **kwargs):
107
+ super().__init__(**kwargs)
108
+ self.google_key = kwargs.get('api_key', GOOGLE_API_KEY)
109
+ self.kwargs = kwargs
110
+
111
+ def extract_location(self, data):
112
+ city = state = state_code = zipcode = None
113
+ try:
114
+ for component in data['address_components']:
115
+ if 'locality' in component['types']:
116
+ city = component['long_name']
117
+ elif 'administrative_area_level_1' in component['types']:
118
+ state_code = component['short_name']
119
+ state = component['long_name']
120
+ elif 'postal_code' in component['types']:
121
+ zipcode = component['long_name']
122
+ except Exception:
123
+ pass
124
+ return city, state, state_code, zipcode
125
+
126
+ def _run(self, query: str) -> dict:
127
+ """Find Location."""
128
+ params = {
129
+ "address": query,
130
+ "key": self.google_key
131
+ }
132
+ response = requests.get(
133
+ self.base_url,
134
+ params=params
135
+ )
136
+ if response.status_code == 200:
137
+ result = response.json()
138
+ if result['status'] == 'OK':
139
+ location = result['results'][0]
140
+ city, state, state_code, zipcode = self.extract_location(
141
+ location
142
+ )
143
+ return {
144
+ "latitude": location['geometry']['location']['lat'],
145
+ "longitude": location['geometry']['location']['lng'],
146
+ "address": location['formatted_address'],
147
+ "place_id": location['place_id'],
148
+ "zipcode": zipcode,
149
+ "city": city,
150
+ "state": state,
151
+ "state_code": state_code
152
+ }
153
+ return None
154
+ else:
155
+ return None
156
+
157
+ class GoogleRouteSearch(BaseTool):
158
+ """Web Search under a site using Google API."""
159
+ name: str = "google_maps_route_search"
160
+ description: str = "Search for a Route to a location using Google Maps, using this tool if answers questions about how to reach a location."
161
+ google_key: str = None
162
+ base_url: str = 'https://maps.googleapis.com/maps/api/directions/json'
163
+
164
+ def __init__(self, **kwargs):
165
+ super().__init__(**kwargs)
166
+ self._key_ = kwargs.get('api_key', GOOGLE_API_KEY)
167
+ self._kwargs = kwargs
168
+
169
+ def _run(self, query: str) -> dict:
170
+ departure_time = 'now'
parrot/tools/stack.py ADDED
@@ -0,0 +1,26 @@
1
+ from langchain.tools import Tool
2
+ from langchain.tools import BaseTool
3
+ from langchain_community.utilities import StackExchangeAPIWrapper
4
+
5
+ class StackExchangeTool(BaseTool):
6
+ """Tool that searches the StackExchangeTool API."""
7
+ name: str = "StackExchangeSearch"
8
+ description: str = (
9
+ "A wrapper around StackExchange API. Stack Exchange is a network of question-and-answer (Q&A) websites on topics in diverse fields, each site covering a specific topic."
10
+ "Useful for when you need to answer general questions about different topics when user requested."
11
+ )
12
+ search: Tool = None
13
+
14
+ def __init__(self, **kwargs):
15
+ super().__init__(**kwargs)
16
+ self.search = StackExchangeAPIWrapper(
17
+ query_type='title',
18
+ max_results=5
19
+ )
20
+
21
+ def _run(
22
+ self,
23
+ query: dict,
24
+ ) -> dict:
25
+ """Use the StackExchangeSearch tool."""
26
+ return self.search.run(query)
@@ -0,0 +1,70 @@
1
+ import requests
2
+ from langchain.tools import BaseTool
3
+ from langchain.tools import Tool
4
+ from langchain_community.utilities import OpenWeatherMapAPIWrapper
5
+ from navconfig import config
6
+ import orjson
7
+
8
+ class OpenWeatherMapTool(BaseTool):
9
+ """Tool that searches the OpenWeatherMap API."""
10
+ name: str = "OpenWeatherMap"
11
+ description: str = (
12
+ "A wrapper around OpenWeatherMap. "
13
+ "Useful for when you need to answer general questions about "
14
+ "weather, temperature, humidity, wind speed, or other weather-related information. "
15
+ )
16
+ search: Tool = None
17
+
18
+ def __init__(self, **kwargs):
19
+ super().__init__(**kwargs)
20
+ self.search = OpenWeatherMapAPIWrapper(
21
+ openweathermap_api_key=config.get('OPENWEATHER_APPID')
22
+ )
23
+
24
+ def _run(
25
+ self,
26
+ query: dict,
27
+ ) -> dict:
28
+ """Use the OpenWeatherMap tool."""
29
+ return self.search.run(query)
30
+
31
+
32
+ class OpenWeather(BaseTool):
33
+ """
34
+ Tool to get weather information about a location.
35
+ """
36
+ name: str = 'openweather_tool'
37
+ description: str = (
38
+ "Get weather information about a location, use this tool to answer questions about weather or weather forecast."
39
+ " Input should be the latitude and longitude of the location you want weather information about."
40
+ )
41
+ base_url: str = 'http://api.openweathermap.org/'
42
+ units: str = 'metric'
43
+ days: int = 3
44
+ appid: str = None
45
+ request: str = 'weather'
46
+ country: str = 'us'
47
+
48
+
49
+ def __init__(self, request: str = 'weather', country: str = 'us', **kwargs):
50
+ super().__init__(**kwargs)
51
+ self.request = request
52
+ self.country = country
53
+ self.appid = config.get('OPENWEATHER_APPID')
54
+
55
+ def _run(self, query: dict) -> dict:
56
+ q = orjson.loads(query) # pylint: disable=no-member
57
+ if 'latitude' in q and 'longitude' in q:
58
+ lat = q['latitude']
59
+ lon = q['longitude']
60
+ if self.request == 'weather':
61
+ url = f"{self.base_url}data/2.5/weather?lat={lat}&lon={lon}&units={self.units}&appid={self.appid}"
62
+ elif self.request == 'forecast':
63
+ url = f"{self.base_url}data/2.5/forecast?lat={lat}&lon={lon}&units={self.units}&cnt={self.days}&appid={self.appid}"
64
+ else:
65
+ return {'error': 'Latitude and longitude are required'}
66
+ response = requests.get(url)
67
+ return response.json()
68
+
69
+ async def _arun(self, query: dict) -> dict:
70
+ raise NotImplementedError("Async method not implemented yet")
@@ -0,0 +1,59 @@
1
+ from typing import Optional, Any
2
+ from langchain_core.callbacks import CallbackManagerForToolRun
3
+ from langchain_community.tools import WikipediaQueryRun
4
+ from langchain_community.utilities import WikipediaAPIWrapper
5
+ from langchain_community.tools.wikidata.tool import WikidataAPIWrapper, WikidataQueryRun
6
+ from langchain.tools import BaseTool
7
+
8
+
9
+ class WikipediaTool(BaseTool):
10
+ """Tool that searches the Wikipedia API."""
11
+ name = "Wikipedia"
12
+ description: str = (
13
+ "A wrapper around Wikipedia. "
14
+ "Useful for searching Wikipedia for general information. "
15
+ "Useful for when you need to answer general questions about "
16
+ "people, places, companies, facts, historical events, or other subjects. "
17
+ "Input should be a search query."
18
+ )
19
+ search: Any = None
20
+
21
+ def __init__(self, **kwargs):
22
+ super().__init__(**kwargs)
23
+ self.search = WikipediaQueryRun(
24
+ api_wrapper=WikipediaAPIWrapper()
25
+ )
26
+
27
+ def _run(
28
+ self,
29
+ query: str,
30
+ run_manager: Optional[CallbackManagerForToolRun] = None,
31
+ ) -> str:
32
+ """Use the Wikipedia tool."""
33
+ return self.search.run(query)
34
+
35
+ class WikidataTool(BaseTool):
36
+ """Tool that searches the Wikidata API."""
37
+ name: str = "Wikidata"
38
+ description: str = (
39
+ "A wrapper around Wikidata. "
40
+ "Useful for when you need to answer general questions about "
41
+ "people, places, companies, facts, historical events, or other subjects. "
42
+ "Input should be the exact name of the item you want information about "
43
+ "or a Wikidata QID."
44
+ )
45
+ search: Any = None
46
+
47
+ def __init__(self, **kwargs):
48
+ super().__init__(**kwargs)
49
+ self.search = WikidataQueryRun(
50
+ api_wrapper=WikidataAPIWrapper()
51
+ )
52
+
53
+ def _run(
54
+ self,
55
+ query: str,
56
+ run_manager: Optional[CallbackManagerForToolRun] = None,
57
+ ) -> str:
58
+ """Use the Wikipedia tool."""
59
+ return self.search.run(query)