ai-parrot 0.3.4__cp39-cp39-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.
- ai_parrot-0.3.4.dist-info/LICENSE +21 -0
- ai_parrot-0.3.4.dist-info/METADATA +319 -0
- ai_parrot-0.3.4.dist-info/RECORD +109 -0
- ai_parrot-0.3.4.dist-info/WHEEL +6 -0
- ai_parrot-0.3.4.dist-info/top_level.txt +3 -0
- parrot/__init__.py +21 -0
- parrot/chatbots/__init__.py +7 -0
- parrot/chatbots/abstract.py +728 -0
- parrot/chatbots/asktroc.py +16 -0
- parrot/chatbots/base.py +366 -0
- parrot/chatbots/basic.py +9 -0
- parrot/chatbots/bose.py +17 -0
- parrot/chatbots/cody.py +17 -0
- parrot/chatbots/copilot.py +83 -0
- parrot/chatbots/dataframe.py +103 -0
- parrot/chatbots/hragents.py +15 -0
- parrot/chatbots/odoo.py +17 -0
- parrot/chatbots/retrievals/__init__.py +578 -0
- parrot/chatbots/retrievals/constitutional.py +19 -0
- parrot/conf.py +110 -0
- parrot/crew/__init__.py +3 -0
- parrot/crew/tools/__init__.py +22 -0
- parrot/crew/tools/bing.py +13 -0
- parrot/crew/tools/config.py +43 -0
- parrot/crew/tools/duckgo.py +62 -0
- parrot/crew/tools/file.py +24 -0
- parrot/crew/tools/google.py +168 -0
- parrot/crew/tools/gtrends.py +16 -0
- parrot/crew/tools/md2pdf.py +25 -0
- parrot/crew/tools/rag.py +42 -0
- parrot/crew/tools/search.py +32 -0
- parrot/crew/tools/url.py +21 -0
- parrot/exceptions.cpython-39-x86_64-linux-gnu.so +0 -0
- parrot/handlers/__init__.py +4 -0
- parrot/handlers/bots.py +196 -0
- parrot/handlers/chat.py +162 -0
- parrot/interfaces/__init__.py +6 -0
- parrot/interfaces/database.py +29 -0
- parrot/llms/__init__.py +137 -0
- parrot/llms/abstract.py +47 -0
- parrot/llms/anthropic.py +42 -0
- parrot/llms/google.py +42 -0
- parrot/llms/groq.py +45 -0
- parrot/llms/hf.py +45 -0
- parrot/llms/openai.py +59 -0
- parrot/llms/pipes.py +114 -0
- parrot/llms/vertex.py +78 -0
- parrot/loaders/__init__.py +20 -0
- parrot/loaders/abstract.py +456 -0
- parrot/loaders/audio.py +106 -0
- parrot/loaders/basepdf.py +102 -0
- parrot/loaders/basevideo.py +280 -0
- parrot/loaders/csv.py +42 -0
- parrot/loaders/dir.py +37 -0
- parrot/loaders/excel.py +349 -0
- parrot/loaders/github.py +65 -0
- parrot/loaders/handlers/__init__.py +5 -0
- parrot/loaders/handlers/data.py +213 -0
- parrot/loaders/image.py +119 -0
- parrot/loaders/json.py +52 -0
- parrot/loaders/pdf.py +437 -0
- parrot/loaders/pdfchapters.py +142 -0
- parrot/loaders/pdffn.py +112 -0
- parrot/loaders/pdfimages.py +207 -0
- parrot/loaders/pdfmark.py +88 -0
- parrot/loaders/pdftables.py +145 -0
- parrot/loaders/ppt.py +30 -0
- parrot/loaders/qa.py +81 -0
- parrot/loaders/repo.py +103 -0
- parrot/loaders/rtd.py +65 -0
- parrot/loaders/txt.py +92 -0
- parrot/loaders/utils/__init__.py +1 -0
- parrot/loaders/utils/models.py +25 -0
- parrot/loaders/video.py +96 -0
- parrot/loaders/videolocal.py +120 -0
- parrot/loaders/vimeo.py +106 -0
- parrot/loaders/web.py +216 -0
- parrot/loaders/web_base.py +112 -0
- parrot/loaders/word.py +125 -0
- parrot/loaders/youtube.py +192 -0
- parrot/manager.py +166 -0
- parrot/models.py +372 -0
- parrot/py.typed +0 -0
- parrot/stores/__init__.py +48 -0
- parrot/stores/abstract.py +171 -0
- parrot/stores/milvus.py +632 -0
- parrot/stores/qdrant.py +153 -0
- parrot/tools/__init__.py +12 -0
- parrot/tools/abstract.py +53 -0
- parrot/tools/asknews.py +32 -0
- parrot/tools/bing.py +13 -0
- parrot/tools/duck.py +62 -0
- parrot/tools/google.py +170 -0
- parrot/tools/stack.py +26 -0
- parrot/tools/weather.py +70 -0
- parrot/tools/wikipedia.py +59 -0
- parrot/tools/zipcode.py +179 -0
- parrot/utils/__init__.py +2 -0
- parrot/utils/parsers/__init__.py +5 -0
- parrot/utils/parsers/toml.cpython-39-x86_64-linux-gnu.so +0 -0
- parrot/utils/toml.py +11 -0
- parrot/utils/types.cpython-39-x86_64-linux-gnu.so +0 -0
- parrot/utils/uv.py +11 -0
- parrot/version.py +10 -0
- resources/users/__init__.py +5 -0
- resources/users/handlers.py +13 -0
- resources/users/models.py +205 -0
- settings/__init__.py +0 -0
- settings/settings.py +51 -0
parrot/crew/__init__.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""
|
|
2
|
+
A Directory for adding more Tools to CrewAI
|
|
3
|
+
"""
|
|
4
|
+
from .duckgo import DuckDuckGoRelevantSearch, DuckDuckGoSearchTool
|
|
5
|
+
from .rag import RagSearchTool
|
|
6
|
+
from .file import SaveFile
|
|
7
|
+
from .bing import BingSearchTool
|
|
8
|
+
from .md2pdf import MarkdownToPDFTool
|
|
9
|
+
from .google import GoogleSearchTool, GoogleSiteSearchTool, GoogleLocationFinder
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
'GoogleSearchTool',
|
|
14
|
+
'GoogleSiteSearchTool',
|
|
15
|
+
'BingSearchTool',
|
|
16
|
+
'DuckDuckGoRelevantSearch',
|
|
17
|
+
'DuckDuckGoSearchTool',
|
|
18
|
+
'RagSearchTool',
|
|
19
|
+
'SaveFile',
|
|
20
|
+
'MarkdownToPDFTool',
|
|
21
|
+
'GoogleLocationFinder',
|
|
22
|
+
]
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from langchain_community.utilities.bing_search import BingSearchAPIWrapper
|
|
2
|
+
from crewai_tools import BaseTool
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class BingSearchTool(BaseTool):
|
|
6
|
+
"""Microsoft Bing Search Tool."""
|
|
7
|
+
name: str = "Microsoft 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)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
|
|
2
|
+
def agent_config(
|
|
3
|
+
provider: str = 'vertexai',
|
|
4
|
+
model: str = 'gemini-pro',
|
|
5
|
+
temperature: float = 0.4,
|
|
6
|
+
top_p: int = 0.5,
|
|
7
|
+
stream: bool = True
|
|
8
|
+
) -> dict:
|
|
9
|
+
agent_config ={
|
|
10
|
+
# "llm": {
|
|
11
|
+
# "provider": provider,
|
|
12
|
+
# "config": {
|
|
13
|
+
# "model": model,
|
|
14
|
+
# "temperature": temperature,
|
|
15
|
+
# "top_p": top_p,
|
|
16
|
+
# "stream": stream
|
|
17
|
+
# }
|
|
18
|
+
# },
|
|
19
|
+
"embedder": {
|
|
20
|
+
"provider": "huggingface",
|
|
21
|
+
"config": {
|
|
22
|
+
"model": "sentence-transformers/sentence-t5-large",
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return agent_config
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def agent_embedder(
|
|
30
|
+
provider: str = 'huggingface',
|
|
31
|
+
model: str = 'sentence-transformers/sentence-t5-large',
|
|
32
|
+
**kwargs
|
|
33
|
+
) -> dict:
|
|
34
|
+
agent_config ={
|
|
35
|
+
"embedder": {
|
|
36
|
+
"provider": "huggingface",
|
|
37
|
+
"config": {
|
|
38
|
+
"model": "sentence-transformers/sentence-t5-large",
|
|
39
|
+
**kwargs
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return agent_config
|
|
@@ -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 crewai_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: PrivateAttr
|
|
16
|
+
_max_results: PrivateAttr
|
|
17
|
+
_region: PrivateAttr
|
|
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
|
+
)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from typing import Union
|
|
2
|
+
from pathlib import Path, PurePath
|
|
3
|
+
from pydantic import PrivateAttr
|
|
4
|
+
from crewai_tools import BaseTool
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class SaveFile(BaseTool):
|
|
8
|
+
"""Save a file to a directory."""
|
|
9
|
+
name: str = "Save File"
|
|
10
|
+
description: str = "Save a file to a directory."
|
|
11
|
+
_directory: PrivateAttr
|
|
12
|
+
|
|
13
|
+
def __init__(self, directory: Union[str, PurePath], **kwargs):
|
|
14
|
+
super().__init__(**kwargs)
|
|
15
|
+
if isinstance(directory, str):
|
|
16
|
+
self._directory = Path(directory).resolve()
|
|
17
|
+
self._directory = directory
|
|
18
|
+
|
|
19
|
+
def _run(self, file: str, **kwargs) -> dict:
|
|
20
|
+
"""Run the Save File Tool."""
|
|
21
|
+
filename = self._directory.joinpath(file)
|
|
22
|
+
with open(filename, "w") as f:
|
|
23
|
+
f.write(kwargs.get("content", ""))
|
|
24
|
+
return {"file": file}
|
|
@@ -0,0 +1,168 @@
|
|
|
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 langchain.tools import Tool
|
|
8
|
+
from navconfig import config
|
|
9
|
+
from ...conf import GOOGLE_API_KEY
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class GoogleSearchTool(BaseTool):
|
|
13
|
+
"""Web Search tool using Google API."""
|
|
14
|
+
name: str = "Google Web Search"
|
|
15
|
+
description: str = "Search the web using Google Search API, useful when you need to answer questions about current events."
|
|
16
|
+
source: str = 'news'
|
|
17
|
+
max_results: int = 5
|
|
18
|
+
region: str = ''
|
|
19
|
+
# Fields populated during init (not required for validation)
|
|
20
|
+
cse_id: Optional[str] = None
|
|
21
|
+
search_key: Optional[str] = None
|
|
22
|
+
kwargs: Optional[dict] = None
|
|
23
|
+
|
|
24
|
+
def __init__(self, source: str = "news", results: int = 5, **kwargs):
|
|
25
|
+
super().__init__(**kwargs)
|
|
26
|
+
self.source = source
|
|
27
|
+
self.max_results = results
|
|
28
|
+
self.cse_id = config.get('GOOGLE_SEARCH_ENGINE_ID')
|
|
29
|
+
self.search_key = config.get('GOOGLE_SEARCH_API_KEY')
|
|
30
|
+
self.kwargs = kwargs
|
|
31
|
+
|
|
32
|
+
def _run(self, query: str) -> list:
|
|
33
|
+
"""Run the Google Search Tool."""
|
|
34
|
+
service = build("customsearch", "v1", developerKey=self.search_key)
|
|
35
|
+
res = service.cse().list(
|
|
36
|
+
q=query,
|
|
37
|
+
cx=self.cse_id,
|
|
38
|
+
num=self.max_results,
|
|
39
|
+
**self.kwargs
|
|
40
|
+
).execute()
|
|
41
|
+
results = []
|
|
42
|
+
for item in res['items']:
|
|
43
|
+
results.append(
|
|
44
|
+
{
|
|
45
|
+
'snippet': item['snippet'],
|
|
46
|
+
'title': item['title'],
|
|
47
|
+
'link': item['link'],
|
|
48
|
+
'description': item['snippet']
|
|
49
|
+
}
|
|
50
|
+
)
|
|
51
|
+
return results
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class GoogleSiteSearchTool(BaseTool):
|
|
55
|
+
"""Web Search under a site using Google API."""
|
|
56
|
+
name: str = "Google Web Search"
|
|
57
|
+
description: str = "Search the web using Google Search API"
|
|
58
|
+
source: str = 'news'
|
|
59
|
+
max_results: int = 5
|
|
60
|
+
region: str = ''
|
|
61
|
+
|
|
62
|
+
def __init__(self, site: str = "news", results: int = 5, **kwargs):
|
|
63
|
+
super().__init__(**kwargs)
|
|
64
|
+
self.source = site
|
|
65
|
+
self.max_results = results
|
|
66
|
+
self._cse_id = config.get('GOOGLE_SEARCH_ENGINE_ID')
|
|
67
|
+
self._search_key = config.get('GOOGLE_SEARCH_API_KEY')
|
|
68
|
+
self._kwargs = kwargs
|
|
69
|
+
|
|
70
|
+
def _run(self, query: str) -> dict:
|
|
71
|
+
"""Run the Google Search Tool."""
|
|
72
|
+
service = build("customsearch", "v1", developerKey=self._search_key)
|
|
73
|
+
qs = f'{query} site:{self.source}'
|
|
74
|
+
res = service.cse().list(
|
|
75
|
+
q=qs,
|
|
76
|
+
cx=self._cse_id,
|
|
77
|
+
num=self.max_results,
|
|
78
|
+
**self._kwargs
|
|
79
|
+
).execute()
|
|
80
|
+
results = []
|
|
81
|
+
for item in res['items']:
|
|
82
|
+
results.append(
|
|
83
|
+
{
|
|
84
|
+
'snippet': item['snippet'],
|
|
85
|
+
'title': item['title'],
|
|
86
|
+
'link': item['link'],
|
|
87
|
+
'description': item['snippet']
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
return results
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class GoogleLocationFinder(BaseTool):
|
|
94
|
+
""" LocationFinder class for finding locations."""
|
|
95
|
+
name: str = "google_maps_location_finder"
|
|
96
|
+
description: str = (
|
|
97
|
+
"Search for location information, use this tool to find latitude, longitude and other geographical information from locations."
|
|
98
|
+
" Provide the complete address to this tool to receive location information"
|
|
99
|
+
)
|
|
100
|
+
google_key: str = None
|
|
101
|
+
base_url: str = "https://maps.googleapis.com/maps/api/geocode/json"
|
|
102
|
+
kwargs: Optional[dict] = None
|
|
103
|
+
|
|
104
|
+
def __init__(self, **kwargs):
|
|
105
|
+
super().__init__(**kwargs)
|
|
106
|
+
self.google_key = kwargs.get('api_key', GOOGLE_API_KEY)
|
|
107
|
+
self.kwargs = kwargs
|
|
108
|
+
|
|
109
|
+
def extract_location(self, data):
|
|
110
|
+
city = state = state_code = zipcode = None
|
|
111
|
+
try:
|
|
112
|
+
for component in data['address_components']:
|
|
113
|
+
if 'locality' in component['types']:
|
|
114
|
+
city = component['long_name']
|
|
115
|
+
elif 'administrative_area_level_1' in component['types']:
|
|
116
|
+
state_code = component['short_name']
|
|
117
|
+
state = component['long_name']
|
|
118
|
+
elif 'postal_code' in component['types']:
|
|
119
|
+
zipcode = component['long_name']
|
|
120
|
+
except Exception:
|
|
121
|
+
pass
|
|
122
|
+
return city, state, state_code, zipcode
|
|
123
|
+
|
|
124
|
+
def _run(self, query: str) -> dict:
|
|
125
|
+
"""Find Location."""
|
|
126
|
+
params = {
|
|
127
|
+
"address": query,
|
|
128
|
+
"key": self.google_key
|
|
129
|
+
}
|
|
130
|
+
response = requests.get(
|
|
131
|
+
self.base_url,
|
|
132
|
+
params=params
|
|
133
|
+
)
|
|
134
|
+
if response.status_code == 200:
|
|
135
|
+
result = response.json()
|
|
136
|
+
if result['status'] == 'OK':
|
|
137
|
+
location = result['results'][0]
|
|
138
|
+
city, state, state_code, zipcode = self.extract_location(
|
|
139
|
+
location
|
|
140
|
+
)
|
|
141
|
+
return {
|
|
142
|
+
"latitude": location['geometry']['location']['lat'],
|
|
143
|
+
"longitude": location['geometry']['location']['lng'],
|
|
144
|
+
"address": location['formatted_address'],
|
|
145
|
+
"place_id": location['place_id'],
|
|
146
|
+
"zipcode": zipcode,
|
|
147
|
+
"city": city,
|
|
148
|
+
"state": state,
|
|
149
|
+
"state_code": state_code
|
|
150
|
+
}
|
|
151
|
+
return None
|
|
152
|
+
else:
|
|
153
|
+
return None
|
|
154
|
+
|
|
155
|
+
class GoogleRouteSearch(BaseTool):
|
|
156
|
+
"""Web Search under a site using Google API."""
|
|
157
|
+
name: str = "google_maps_route_search"
|
|
158
|
+
description: str = "Search for a Route to a location using Google Maps, using this tool if answers questions about how to reach a location."
|
|
159
|
+
google_key: str = None
|
|
160
|
+
base_url: str = 'https://maps.googleapis.com/maps/api/directions/json'
|
|
161
|
+
|
|
162
|
+
def __init__(self, **kwargs):
|
|
163
|
+
super().__init__(**kwargs)
|
|
164
|
+
self._key_ = kwargs.get('api_key', GOOGLE_API_KEY)
|
|
165
|
+
self._kwargs = kwargs
|
|
166
|
+
|
|
167
|
+
def _run(self, query: str) -> dict:
|
|
168
|
+
departure_time = 'now'
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from langchain_community.tools.google_trends import GoogleTrendsQueryRun
|
|
2
|
+
from langchain_community.utilities.google_trends import GoogleTrendsAPIWrapper
|
|
3
|
+
from crewai_tools import BaseTool
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class GoogleTrendsTool(BaseTool):
|
|
7
|
+
"""Google Trends Tool."""
|
|
8
|
+
name: str = "Google Trends"
|
|
9
|
+
description: str = "Search the web using Google Trends API"
|
|
10
|
+
|
|
11
|
+
def _run(self, query: str) -> dict:
|
|
12
|
+
"""Run the Google Trends Tool."""
|
|
13
|
+
google_trends = GoogleTrendsQueryRun(
|
|
14
|
+
api_wrapper=GoogleTrendsAPIWrapper()
|
|
15
|
+
)
|
|
16
|
+
return google_trends.run(query)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from navconfig import BASE_DIR
|
|
2
|
+
from crewai_tools import BaseTool
|
|
3
|
+
import markdown2
|
|
4
|
+
from weasyprint import HTML
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class MarkdownToPDFTool(BaseTool):
|
|
8
|
+
"""Markdown to PDF Tool."""
|
|
9
|
+
name: str = "MarkdownToPDFTool"
|
|
10
|
+
description: str = "Converts markdown documents to PDF format."
|
|
11
|
+
|
|
12
|
+
def _run(self, markdown_content: str) -> str:
|
|
13
|
+
# Convert Markdown to HTML
|
|
14
|
+
html_content = markdown2.markdown(markdown_content)
|
|
15
|
+
# Convert HTML to PDF (assuming it's a simple conversion without advanced styling)
|
|
16
|
+
pdf = HTML(string=html_content).write_pdf()
|
|
17
|
+
|
|
18
|
+
# Save PDF to a temporary file and return file path
|
|
19
|
+
pdf_file_path = BASE_DIR.joinpath('docs', 'report.pdf')
|
|
20
|
+
with open(str(pdf_file_path), 'wb') as f:
|
|
21
|
+
f.write(pdf)
|
|
22
|
+
return pdf_file_path
|
|
23
|
+
|
|
24
|
+
def __call__(self, markdown_content: str) -> str:
|
|
25
|
+
return self._run(markdown_content)
|
parrot/crew/tools/rag.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from typing import Union
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from pydantic import PrivateAttr
|
|
4
|
+
from crewai_tools import BaseTool, RagTool
|
|
5
|
+
|
|
6
|
+
class RagSearchTool(BaseTool):
|
|
7
|
+
"""RagTool is designed to answer questions by leveraging the power of RAG by leveraging (EmbedChain)."""
|
|
8
|
+
name: str = "RAG Tool"
|
|
9
|
+
description: str = "enables users to dynamically query a knowledge base"
|
|
10
|
+
_directory: PrivateAttr
|
|
11
|
+
|
|
12
|
+
def __init__(self, directory: Union[Path, str] = None, **kwargs):
|
|
13
|
+
super().__init__(**kwargs)
|
|
14
|
+
self._directory = directory
|
|
15
|
+
|
|
16
|
+
def get_rag(self):
|
|
17
|
+
"""Return the RAG Tool."""
|
|
18
|
+
return RagTool(
|
|
19
|
+
config={
|
|
20
|
+
"llm": {
|
|
21
|
+
"provider": "vertexai",
|
|
22
|
+
"config": {
|
|
23
|
+
"model": "gemini-pro",
|
|
24
|
+
"temperature": 0.4,
|
|
25
|
+
"top_p": 1,
|
|
26
|
+
"stream": True
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"embedder": {
|
|
30
|
+
"provider": "vertexai",
|
|
31
|
+
"config": {
|
|
32
|
+
"model": "embedding-001"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
def _run(self, query: str, **kwargs) -> dict:
|
|
39
|
+
"""Query Several sources of information for knowledge base."""
|
|
40
|
+
rag = self.get_rag()
|
|
41
|
+
if self._directory:
|
|
42
|
+
return rag.from_directory(self._directory)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from crewai_tools import WebsiteSearchTool
|
|
2
|
+
from crewai_tools import BaseTool
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class WebSearchTool(BaseTool):
|
|
6
|
+
"""Search on any Website using WebSiteSearch."""
|
|
7
|
+
name: str = "WebSite Search"
|
|
8
|
+
description: str = "Search on a website using WebsiteSearchTool"
|
|
9
|
+
|
|
10
|
+
def _run(self, query: str, **kwargs) -> dict:
|
|
11
|
+
"""Run the Google Trends Tool."""
|
|
12
|
+
search = WebsiteSearchTool(
|
|
13
|
+
config={
|
|
14
|
+
"llm": {
|
|
15
|
+
"provider": "google",
|
|
16
|
+
"config": {
|
|
17
|
+
"model": "models/gemini-pro",
|
|
18
|
+
"temperature": 0.4,
|
|
19
|
+
"top_p": 1,
|
|
20
|
+
"stream": True
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"embedder": {
|
|
24
|
+
"provider": "google",
|
|
25
|
+
"config": {
|
|
26
|
+
"model": "models/embedding-001",
|
|
27
|
+
"task_type": "retrieval_document",
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
)
|
|
32
|
+
return search.run(query, **kwargs)
|
parrot/crew/tools/url.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
from crewai_tools import BaseTool
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class ValidateURLsTool(BaseTool):
|
|
6
|
+
"""Validate URLs Tool."""
|
|
7
|
+
name: str = "Validate URLs"
|
|
8
|
+
description: str = "Validate URLs for status code and response time."
|
|
9
|
+
|
|
10
|
+
def _run(self, urls: list) -> dict:
|
|
11
|
+
"""Run the Validate URLs Tool."""
|
|
12
|
+
valid_urls = []
|
|
13
|
+
for url in urls:
|
|
14
|
+
try:
|
|
15
|
+
response = requests.head(url, allow_redirects=True)
|
|
16
|
+
if response.status_code == 200:
|
|
17
|
+
valid_urls.append(url)
|
|
18
|
+
except requests.RequestException:
|
|
19
|
+
# Handle exceptions or log errors here
|
|
20
|
+
continue
|
|
21
|
+
return valid_urls
|
|
Binary file
|
parrot/handlers/bots.py
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
from asyncdb import AsyncDB
|
|
2
|
+
from navigator.views import (
|
|
3
|
+
ModelView,
|
|
4
|
+
BaseView,
|
|
5
|
+
FormModel
|
|
6
|
+
)
|
|
7
|
+
from parrot.conf import (
|
|
8
|
+
BIGQUERY_CREDENTIALS,
|
|
9
|
+
BIGQUERY_PROJECT_ID,
|
|
10
|
+
)
|
|
11
|
+
from ..models import (
|
|
12
|
+
ChatbotModel,
|
|
13
|
+
ChatbotUsage,
|
|
14
|
+
PromptLibrary,
|
|
15
|
+
ChatbotFeedback,
|
|
16
|
+
FeedbackType
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class PromptLibraryManagement(ModelView):
|
|
21
|
+
"""
|
|
22
|
+
PromptLibraryManagement.
|
|
23
|
+
description: PromptLibraryManagement for Parrot Application.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
model = PromptLibrary
|
|
27
|
+
name: str = "Prompt Library Management"
|
|
28
|
+
path: str = '/api/v1/prompt_library'
|
|
29
|
+
pk: str = 'prompt_id'
|
|
30
|
+
|
|
31
|
+
async def _set_created_by(self, value, column, data):
|
|
32
|
+
if not value:
|
|
33
|
+
return await self.get_userid(session=self._session)
|
|
34
|
+
return value
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class ChatbotUsageHandler(ModelView):
|
|
38
|
+
"""
|
|
39
|
+
ChatbotUsageHandler.
|
|
40
|
+
description: ChatbotUsageHandler for Parrot Application.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
model = ChatbotUsage
|
|
44
|
+
driver: str = 'scylladb'
|
|
45
|
+
credentials: dict = {
|
|
46
|
+
"credentials": BIGQUERY_CREDENTIALS,
|
|
47
|
+
"project_id": BIGQUERY_PROJECT_ID,
|
|
48
|
+
}
|
|
49
|
+
name: str = "Chatbot Usage"
|
|
50
|
+
path: str = '/api/v1/chatbots/usage'
|
|
51
|
+
pk: str = 'sid'
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class ChatbotSharingQuestion(BaseView):
|
|
55
|
+
"""
|
|
56
|
+
ChatbotSharingQuestion.
|
|
57
|
+
description: ChatbotSharingQuestion for Parrot Application.
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
def get_connection(self):
|
|
61
|
+
params = {
|
|
62
|
+
"credentials": BIGQUERY_CREDENTIALS,
|
|
63
|
+
"project_id": BIGQUERY_PROJECT_ID,
|
|
64
|
+
}
|
|
65
|
+
return AsyncDB(
|
|
66
|
+
'bigquery',
|
|
67
|
+
params=params
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
async def get(self):
|
|
71
|
+
qs = self.get_arguments(self.request)
|
|
72
|
+
sid = qs.get('sid', None)
|
|
73
|
+
if not sid:
|
|
74
|
+
return self.error(
|
|
75
|
+
response={
|
|
76
|
+
"message": "You need to Provided a ID of Question"
|
|
77
|
+
},
|
|
78
|
+
status=400
|
|
79
|
+
)
|
|
80
|
+
db = self.get_connection()
|
|
81
|
+
try:
|
|
82
|
+
async with await db.connection() as conn: #pylint: disable=E1101
|
|
83
|
+
ChatbotUsage.Meta.connection = conn
|
|
84
|
+
# Getting a SID from sid
|
|
85
|
+
question = await ChatbotUsage.get(sid=sid)
|
|
86
|
+
if not question:
|
|
87
|
+
return self.error(
|
|
88
|
+
response={
|
|
89
|
+
"message": "Question not found"
|
|
90
|
+
},
|
|
91
|
+
status=404
|
|
92
|
+
)
|
|
93
|
+
return self.json_response(
|
|
94
|
+
{
|
|
95
|
+
"chatbot": question.chatbot_id,
|
|
96
|
+
"question": question.question,
|
|
97
|
+
"answer": question.response,
|
|
98
|
+
"at": question.used_at
|
|
99
|
+
}
|
|
100
|
+
)
|
|
101
|
+
except Exception as e:
|
|
102
|
+
return self.error(
|
|
103
|
+
response={
|
|
104
|
+
"message": f"Error on Chatbot Sharing Question: {e}"
|
|
105
|
+
},
|
|
106
|
+
status=400
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class FeedbackTypeHandler(BaseView):
|
|
112
|
+
"""
|
|
113
|
+
FeedbackTypeHandler.
|
|
114
|
+
description: FeedbackTypeHandler for Parrot Application.
|
|
115
|
+
"""
|
|
116
|
+
|
|
117
|
+
async def get(self):
|
|
118
|
+
qs = self.get_arguments(self.request)
|
|
119
|
+
category = qs.get('feedback_type', 'good').capitalize()
|
|
120
|
+
feedback_list = FeedbackType.list_feedback(category)
|
|
121
|
+
return self.json_response({
|
|
122
|
+
"feedback": feedback_list
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
# Manage Feedback:
|
|
126
|
+
class ChatbotFeedbackHandler(FormModel):
|
|
127
|
+
"""
|
|
128
|
+
ChatbotFeedbackHandler.
|
|
129
|
+
description: ChatbotFeedbackHandler for Parrot Application.
|
|
130
|
+
"""
|
|
131
|
+
model = ChatbotFeedback
|
|
132
|
+
path: str = '/api/v1/bot_feedback'
|
|
133
|
+
|
|
134
|
+
def get_connection(self):
|
|
135
|
+
params = {
|
|
136
|
+
"credentials": BIGQUERY_CREDENTIALS,
|
|
137
|
+
"project_id": BIGQUERY_PROJECT_ID,
|
|
138
|
+
}
|
|
139
|
+
return AsyncDB(
|
|
140
|
+
'bigquery',
|
|
141
|
+
params=params,
|
|
142
|
+
force_closing=False
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
async def post(self):
|
|
146
|
+
feedback = await self.validate_payload()
|
|
147
|
+
if not feedback:
|
|
148
|
+
return self.error(
|
|
149
|
+
response={
|
|
150
|
+
"message": "Error on Bot Feedback"
|
|
151
|
+
},
|
|
152
|
+
status=400
|
|
153
|
+
)
|
|
154
|
+
db = self.get_connection()
|
|
155
|
+
try:
|
|
156
|
+
async with await db.connection() as conn: #pylint: disable=E1101
|
|
157
|
+
data = feedback.to_dict()
|
|
158
|
+
# convert to string (bigquery uses json.dumps to convert to string)
|
|
159
|
+
data['sid'] = str(data['sid'])
|
|
160
|
+
data['chatbot_id'] = str(data['chatbot_id'])
|
|
161
|
+
data['expiration_timestamp'] = str(data['expiration_timestamp'])
|
|
162
|
+
data['feedback_type'] = feedback.feedback_type.value
|
|
163
|
+
# writing directly to bigquery
|
|
164
|
+
await conn.write(
|
|
165
|
+
[data],
|
|
166
|
+
table_id=ChatbotFeedback.Meta.name,
|
|
167
|
+
dataset_id=ChatbotFeedback.Meta.schema,
|
|
168
|
+
use_streams=False,
|
|
169
|
+
use_pandas=False
|
|
170
|
+
)
|
|
171
|
+
return self.json_response({
|
|
172
|
+
"message": "Bot Feedback Submitted, Thank you for your feedback!.",
|
|
173
|
+
"question": f"Question of ID: {feedback.sid} for bot {feedback.chatbot_id}"
|
|
174
|
+
}, status=201)
|
|
175
|
+
except Exception as e:
|
|
176
|
+
return self.error(
|
|
177
|
+
response={
|
|
178
|
+
"message": f"Error on Bot Feedback: {e}"
|
|
179
|
+
},
|
|
180
|
+
status=400
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class ChatbotHandler(ModelView):
|
|
185
|
+
"""
|
|
186
|
+
ChatbotHandler.
|
|
187
|
+
description: ChatbotHandler for Parrot Application.
|
|
188
|
+
"""
|
|
189
|
+
|
|
190
|
+
model = ChatbotModel
|
|
191
|
+
name: str = "Chatbot Management"
|
|
192
|
+
pk: str = 'chatbot_id'
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
async def _set_created_by(self, value, column, data):
|
|
196
|
+
return await self.get_userid(session=self._session)
|