ai-parrot 0.8.3__cp310-cp310-manylinux2014_x86_64.manylinux_2_17_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 (128) hide show
  1. ai_parrot-0.8.3.dist-info/LICENSE +21 -0
  2. ai_parrot-0.8.3.dist-info/METADATA +306 -0
  3. ai_parrot-0.8.3.dist-info/RECORD +128 -0
  4. ai_parrot-0.8.3.dist-info/WHEEL +6 -0
  5. ai_parrot-0.8.3.dist-info/top_level.txt +2 -0
  6. parrot/__init__.py +30 -0
  7. parrot/bots/__init__.py +5 -0
  8. parrot/bots/abstract.py +1115 -0
  9. parrot/bots/agent.py +492 -0
  10. parrot/bots/basic.py +9 -0
  11. parrot/bots/bose.py +17 -0
  12. parrot/bots/chatbot.py +271 -0
  13. parrot/bots/cody.py +17 -0
  14. parrot/bots/copilot.py +117 -0
  15. parrot/bots/data.py +730 -0
  16. parrot/bots/dataframe.py +103 -0
  17. parrot/bots/hrbot.py +15 -0
  18. parrot/bots/interfaces/__init__.py +1 -0
  19. parrot/bots/interfaces/retrievers.py +12 -0
  20. parrot/bots/notebook.py +619 -0
  21. parrot/bots/odoo.py +17 -0
  22. parrot/bots/prompts/__init__.py +41 -0
  23. parrot/bots/prompts/agents.py +91 -0
  24. parrot/bots/prompts/data.py +214 -0
  25. parrot/bots/retrievals/__init__.py +1 -0
  26. parrot/bots/retrievals/constitutional.py +19 -0
  27. parrot/bots/retrievals/multi.py +122 -0
  28. parrot/bots/retrievals/retrieval.py +610 -0
  29. parrot/bots/tools/__init__.py +7 -0
  30. parrot/bots/tools/eda.py +325 -0
  31. parrot/bots/tools/pdf.py +50 -0
  32. parrot/bots/tools/plot.py +48 -0
  33. parrot/bots/troc.py +16 -0
  34. parrot/conf.py +170 -0
  35. parrot/crew/__init__.py +3 -0
  36. parrot/crew/tools/__init__.py +22 -0
  37. parrot/crew/tools/bing.py +13 -0
  38. parrot/crew/tools/config.py +43 -0
  39. parrot/crew/tools/duckgo.py +62 -0
  40. parrot/crew/tools/file.py +24 -0
  41. parrot/crew/tools/google.py +168 -0
  42. parrot/crew/tools/gtrends.py +16 -0
  43. parrot/crew/tools/md2pdf.py +25 -0
  44. parrot/crew/tools/rag.py +42 -0
  45. parrot/crew/tools/search.py +32 -0
  46. parrot/crew/tools/url.py +21 -0
  47. parrot/exceptions.cpython-310-x86_64-linux-gnu.so +0 -0
  48. parrot/handlers/__init__.py +4 -0
  49. parrot/handlers/agents.py +292 -0
  50. parrot/handlers/bots.py +196 -0
  51. parrot/handlers/chat.py +192 -0
  52. parrot/interfaces/__init__.py +6 -0
  53. parrot/interfaces/database.py +27 -0
  54. parrot/interfaces/http.py +805 -0
  55. parrot/interfaces/images/__init__.py +0 -0
  56. parrot/interfaces/images/plugins/__init__.py +18 -0
  57. parrot/interfaces/images/plugins/abstract.py +58 -0
  58. parrot/interfaces/images/plugins/exif.py +709 -0
  59. parrot/interfaces/images/plugins/hash.py +52 -0
  60. parrot/interfaces/images/plugins/vision.py +104 -0
  61. parrot/interfaces/images/plugins/yolo.py +66 -0
  62. parrot/interfaces/images/plugins/zerodetect.py +197 -0
  63. parrot/llms/__init__.py +1 -0
  64. parrot/llms/abstract.py +69 -0
  65. parrot/llms/anthropic.py +58 -0
  66. parrot/llms/gemma.py +15 -0
  67. parrot/llms/google.py +44 -0
  68. parrot/llms/groq.py +67 -0
  69. parrot/llms/hf.py +45 -0
  70. parrot/llms/openai.py +61 -0
  71. parrot/llms/pipes.py +114 -0
  72. parrot/llms/vertex.py +89 -0
  73. parrot/loaders/__init__.py +9 -0
  74. parrot/loaders/abstract.py +628 -0
  75. parrot/loaders/files/__init__.py +0 -0
  76. parrot/loaders/files/abstract.py +39 -0
  77. parrot/loaders/files/text.py +63 -0
  78. parrot/loaders/txt.py +26 -0
  79. parrot/manager.py +333 -0
  80. parrot/models.py +504 -0
  81. parrot/py.typed +0 -0
  82. parrot/stores/__init__.py +11 -0
  83. parrot/stores/abstract.py +248 -0
  84. parrot/stores/chroma.py +188 -0
  85. parrot/stores/duck.py +162 -0
  86. parrot/stores/embeddings/__init__.py +10 -0
  87. parrot/stores/embeddings/abstract.py +46 -0
  88. parrot/stores/embeddings/base.py +52 -0
  89. parrot/stores/embeddings/bge.py +20 -0
  90. parrot/stores/embeddings/fastembed.py +17 -0
  91. parrot/stores/embeddings/google.py +18 -0
  92. parrot/stores/embeddings/huggingface.py +20 -0
  93. parrot/stores/embeddings/ollama.py +14 -0
  94. parrot/stores/embeddings/openai.py +26 -0
  95. parrot/stores/embeddings/transformers.py +21 -0
  96. parrot/stores/embeddings/vertexai.py +17 -0
  97. parrot/stores/empty.py +10 -0
  98. parrot/stores/faiss.py +160 -0
  99. parrot/stores/milvus.py +397 -0
  100. parrot/stores/postgres.py +653 -0
  101. parrot/stores/qdrant.py +170 -0
  102. parrot/tools/__init__.py +23 -0
  103. parrot/tools/abstract.py +68 -0
  104. parrot/tools/asknews.py +33 -0
  105. parrot/tools/basic.py +51 -0
  106. parrot/tools/bby.py +359 -0
  107. parrot/tools/bing.py +13 -0
  108. parrot/tools/docx.py +343 -0
  109. parrot/tools/duck.py +62 -0
  110. parrot/tools/execute.py +56 -0
  111. parrot/tools/gamma.py +28 -0
  112. parrot/tools/google.py +170 -0
  113. parrot/tools/gvoice.py +301 -0
  114. parrot/tools/results.py +278 -0
  115. parrot/tools/stack.py +27 -0
  116. parrot/tools/weather.py +70 -0
  117. parrot/tools/wikipedia.py +58 -0
  118. parrot/tools/zipcode.py +198 -0
  119. parrot/utils/__init__.py +2 -0
  120. parrot/utils/parsers/__init__.py +5 -0
  121. parrot/utils/parsers/toml.cpython-310-x86_64-linux-gnu.so +0 -0
  122. parrot/utils/toml.py +11 -0
  123. parrot/utils/types.cpython-310-x86_64-linux-gnu.so +0 -0
  124. parrot/utils/uv.py +11 -0
  125. parrot/version.py +10 -0
  126. resources/users/__init__.py +5 -0
  127. resources/users/handlers.py +13 -0
  128. resources/users/models.py +205 -0
parrot/bots/chatbot.py ADDED
@@ -0,0 +1,271 @@
1
+ """
2
+ Foundational base of every Chatbot and Agent in ai-parrot.
3
+ """
4
+ from typing import Any, Union
5
+ from pathlib import Path, PurePath
6
+ import uuid
7
+ from aiohttp import web
8
+ # Navconfig
9
+ from datamodel.exceptions import ValidationError
10
+ from navconfig import BASE_DIR
11
+ from navconfig.exceptions import ConfigError # pylint: disable=E0611
12
+ from asyncdb.exceptions import NoDataFound
13
+ from ..utils import parse_toml_config
14
+ from ..conf import (
15
+ default_dsn,
16
+ EMBEDDING_DEFAULT_MODEL,
17
+ )
18
+ from ..models import ChatbotModel
19
+ from .abstract import AbstractBot
20
+
21
+ class Chatbot(AbstractBot):
22
+ """Represents an Bot (Chatbot, Agent) in Navigator.
23
+
24
+ Each Chatbot has a name, a role, a goal, a backstory,
25
+ and an optional language model (llm).
26
+ """
27
+ def __init__(
28
+ self,
29
+ name: str = 'Nav',
30
+ system_prompt: str = None,
31
+ human_prompt: str = None,
32
+ **kwargs
33
+ ):
34
+ """Initialize the Chatbot with the given configuration."""
35
+ # Configuration File:
36
+ self.config_file: PurePath = kwargs.get('config_file', None)
37
+ # Other Configuration
38
+ self.confidence_threshold: float = kwargs.get('threshold', 0.5)
39
+ # Text Documents
40
+ self.documents_dir = kwargs.get(
41
+ 'documents_dir',
42
+ None
43
+ )
44
+ super().__init__(
45
+ name=name,
46
+ system_prompt=system_prompt,
47
+ human_prompt=human_prompt,
48
+ **kwargs
49
+ )
50
+ if isinstance(self.documents_dir, str):
51
+ self.documents_dir = Path(self.documents_dir)
52
+ if not self.documents_dir:
53
+ self.documents_dir = BASE_DIR.joinpath('documents')
54
+ if not self.documents_dir.exists():
55
+ self.documents_dir.mkdir(
56
+ parents=True,
57
+ exist_ok=True
58
+ )
59
+ # define de Config File:
60
+ if self.config_file:
61
+ if isinstance(self.config_file, str):
62
+ self.config_file = Path(self.config_file)
63
+ if not self.config_file.exists():
64
+ raise ConfigError(
65
+ f"Configuration file {self.config_file} not found."
66
+ )
67
+
68
+ def __repr__(self):
69
+ return f"<ChatBot.{self.__class__.__name__}:{self.name}>"
70
+
71
+ async def configure(self, app = None) -> None:
72
+ """Load configuration for this Chatbot."""
73
+ await super().configure(app)
74
+ # Check if a Config File exists for this Bot instance:
75
+ config_file = BASE_DIR.joinpath(
76
+ 'etc',
77
+ 'config',
78
+ 'chatbots',
79
+ self.name.lower(),
80
+ "config.toml"
81
+ )
82
+ if not config_file.exists():
83
+ config_file = self.config_file or config_file
84
+ if config_file.exists():
85
+ self.logger.notice(
86
+ f"Loading Bot {self.name} from config: {config_file.name}"
87
+ )
88
+ # Configure from the TOML file
89
+ await self.from_config_file(config_file)
90
+ elif (bot := await self.bot_exists(name=self.name, uuid=self.chatbot_id)):
91
+ self.logger.notice(
92
+ f"Loading Bot {self.name} from Database: {bot.chatbot_id}"
93
+ )
94
+ # Bot exists on Database, Configure from the Database
95
+ await self.from_database(bot, config_file)
96
+ else:
97
+ raise ValueError(
98
+ f'Bad configuration procedure for bot {self.name}'
99
+ )
100
+
101
+ def _from_bot(self, bot, key, config, default) -> Any:
102
+ value = getattr(bot, key, None)
103
+ file_value = config.get(key, default)
104
+ return value if value else file_value
105
+
106
+ def _from_db(self, botobj, key, default = None) -> Any:
107
+ value = getattr(botobj, key, default)
108
+ return value if value else default
109
+
110
+ async def bot_exists(
111
+ self,
112
+ name: str = None,
113
+ uuid: uuid.UUID = None
114
+ ) -> Union[ChatbotModel, bool]:
115
+ """Check if the Chatbot exists in the Database."""
116
+ db = self.get_database('pg', dsn=default_dsn)
117
+ async with await db.connection() as conn: # pylint: disable=E1101
118
+ ChatbotModel.Meta.connection = conn
119
+ try:
120
+ if self.chatbot_id:
121
+ try:
122
+ bot = await ChatbotModel.get(chatbot_id=uuid)
123
+ except Exception:
124
+ bot = await ChatbotModel.get(name=name)
125
+ else:
126
+ bot = await ChatbotModel.get(name=self.name)
127
+ if bot:
128
+ return bot
129
+ else:
130
+ return False
131
+ except NoDataFound:
132
+ return False
133
+
134
+ async def from_database(
135
+ self,
136
+ bot: Union[ChatbotModel, None] = None,
137
+ config_file: PurePath = None
138
+ ) -> None:
139
+ """Load the Chatbot Configuration from the Database."""
140
+ if not bot:
141
+ db = self.get_database('pg', dsn=default_dsn)
142
+ async with await db.connection() as conn: # pylint: disable=E1101
143
+ # import model
144
+ ChatbotModel.Meta.connection = conn
145
+ try:
146
+ if self.chatbot_id:
147
+ try:
148
+ bot = await ChatbotModel.get(chatbot_id=self.chatbot_id)
149
+ except Exception:
150
+ bot = await ChatbotModel.get(name=self.name)
151
+ else:
152
+ bot = await ChatbotModel.get(name=self.name)
153
+ except ValidationError as ex:
154
+ # Handle ValidationError
155
+ self.logger.error(
156
+ f"Validation error: {ex}"
157
+ )
158
+ raise ConfigError(
159
+ f"Chatbot {self.name} with errors: {ex.payload()}."
160
+ )
161
+ except NoDataFound:
162
+ # Fallback to File configuration:
163
+ raise ConfigError(
164
+ f"Chatbot {self.name} not found in the database."
165
+ )
166
+ # Start Bot configuration from Database:
167
+ if config_file and config_file.exists():
168
+ file_config = await parse_toml_config(config_file)
169
+ # Knowledge Base come from file:
170
+ # Contextual knowledge-base
171
+ self.kb = file_config.get('knowledge-base', [])
172
+ if self.kb:
173
+ self.knowledge_base = self.create_kb(
174
+ self.kb.get('data', [])
175
+ )
176
+ self.name = self._from_db(bot, 'name', default=self.name)
177
+ self.chatbot_id = str(self._from_db(bot, 'chatbot_id', default=self.chatbot_id))
178
+ self.description = self._from_db(bot, 'description', default=self.description)
179
+ self.role = self._from_db(bot, 'role', default=self.role)
180
+ self.goal = self._from_db(bot, 'goal', default=self.goal)
181
+ self.rationale = self._from_db(bot, 'rationale', default=self.rationale)
182
+ self.backstory = self._from_db(bot, 'backstory', default=self.backstory)
183
+ # LLM Configuration:
184
+ llm = self._from_db(bot, 'llm', default='vertexai')
185
+ llm_config = self._from_db(bot, 'llm_config', default={})
186
+ # Configuration of LLM:
187
+ self.configure_llm(llm, llm_config)
188
+ # Embedding Model Configuration:
189
+ self.embedding_model : dict = self._from_db(
190
+ bot, 'embedding_model', None
191
+ )
192
+ # Database Configuration:
193
+ self._use_vector = bot.vector_store
194
+ self._vector_store = bot.database
195
+ self.configure_store()
196
+ # after configuration, setup the chatbot
197
+ if bot.system_prompt_template:
198
+ self.system_prompt_template = bot.system_prompt_template
199
+ self._define_prompt(
200
+ config={}
201
+ )
202
+ # Last: permissions:
203
+ _default = self.default_permissions()
204
+ _permissions = bot.permissions
205
+ self._permissions = {**_default, **_permissions}
206
+
207
+ async def from_config_file(self, config_file: PurePath) -> None:
208
+ """Load the Chatbot Configuration from the TOML file."""
209
+ self.logger.debug(
210
+ f"Using Config File: {config_file}"
211
+ )
212
+ file_config = await parse_toml_config(config_file)
213
+ # getting the configuration from config
214
+ self.config_file = config_file
215
+ # basic config
216
+ basic = file_config.get('chatbot', {})
217
+ # Chatbot Name:
218
+ self.name = basic.get('name', self.name)
219
+ self.description = basic.get('description', self.description)
220
+ self.role = basic.get('role', self.role)
221
+ self.goal = basic.get('goal', self.goal)
222
+ self.rationale = basic.get('rationale', self.rationale)
223
+ self.backstory = basic.get('backstory', self.backstory)
224
+ # Model Information:
225
+ llminfo = file_config.get('llm')
226
+ llm = llminfo.get('llm', 'VertexLLM')
227
+ cfg = llminfo.get('config', {})
228
+ # Configuration of LLM:
229
+ self.configure_llm(llm, cfg)
230
+ # Other models and embedding models:
231
+ models = file_config.get('models', {})
232
+ self.embedding_model = models.get(
233
+ 'embedding_model',
234
+ {
235
+ 'model': EMBEDDING_DEFAULT_MODEL,
236
+ 'model_type': 'transformers'
237
+ }
238
+ )
239
+ # pre-instructions
240
+ instructions = file_config.get('pre-instructions')
241
+ if instructions:
242
+ self.pre_instructions = instructions.get('instructions', [])
243
+ # Contextual knowledge-base
244
+ self.kb = file_config.get('knowledge-base', [])
245
+ if self.kb:
246
+ self.knowledge_base = self.create_kb(
247
+ self.kb.get('data', [])
248
+ )
249
+ database = file_config.get('database', {})
250
+ vector_store = database.get('vector_store', False)
251
+ if database or vector_store is True:
252
+ self._use_database = True
253
+ vector_db = database.pop('vector_database', None)
254
+ # configure vector database:
255
+ if vector_db:
256
+ # Initialize the store:
257
+ self.stores = []
258
+ self.store = None
259
+ self._use_vector = vector_store
260
+ self._vector_store = database
261
+ self.configure_store()
262
+ # after configuration, setup the chatbot
263
+ if 'template_prompt' in basic:
264
+ self.template_prompt = basic.get('template_prompt')
265
+ self._define_prompt(
266
+ config=basic
267
+ )
268
+ # Last: permissions:
269
+ permissions = file_config.get('permissions', {})
270
+ _default = self.default_permissions()
271
+ self._permissions = {**_default, **permissions}
parrot/bots/cody.py ADDED
@@ -0,0 +1,17 @@
1
+ from .chatbot import Chatbot
2
+
3
+ class Cody(Chatbot):
4
+ """Represents a Python expert in Navigator.
5
+
6
+ Each expert has a name, a role, a goal, a backstory,
7
+ and an optional language model (llm).
8
+ """
9
+ name: str = 'Cody'
10
+ company_information: dict = {
11
+ 'company': 'T-ROC Global',
12
+ 'company_website': 'https://www.trocglobal.com',
13
+ 'contact_email': 'communications@trocglobal.com',
14
+ 'contact_form': 'https://www.surveymonkey.com/r/TROC_Suggestion_Box'
15
+ }
16
+ role: str = 'Python Expert'
17
+ goal = 'Provide useful information about Python programming to employees.'
parrot/bots/copilot.py ADDED
@@ -0,0 +1,117 @@
1
+ from langchain_experimental.tools.python.tool import PythonAstREPLTool
2
+ from .agent import BaseAgent
3
+ # importing Tools
4
+ from ..tools import (
5
+ # ZipcodeAPIToolkit,
6
+ # WikipediaTool,
7
+ # WikidataTool,
8
+ GoogleSearchTool,
9
+ GoogleLocationFinder,
10
+ BingSearchTool,
11
+ # AskNewsTool,
12
+ DuckDuckGoSearchTool,
13
+ YouTubeSearchTool,
14
+ OpenWeatherMapTool,
15
+ StackExchangeTool,
16
+ )
17
+ from ..tools.execute import ExecutablePythonREPLTool
18
+
19
+ # ZipCode API Toolkit
20
+ # zpt = ZipcodeAPIToolkit()
21
+ # zpt_tools = zpt.get_tools()
22
+
23
+ # wk1 = WikipediaTool()
24
+ # wk12 = WikidataTool()
25
+
26
+ g1 = GoogleSearchTool()
27
+ g2 = GoogleLocationFinder()
28
+
29
+ b = BingSearchTool()
30
+ d = DuckDuckGoSearchTool()
31
+ # ask = AskNewsTool()
32
+
33
+ yt = YouTubeSearchTool()
34
+ stackexchange = StackExchangeTool()
35
+ weather = OpenWeatherMapTool()
36
+
37
+ tooling = [
38
+ # wk1,
39
+ g1, g2,
40
+ b, d, yt,
41
+ weather,
42
+ stackexchange
43
+ ] # + zpt_tools
44
+
45
+ class CopilotAgent(BaseAgent):
46
+ """CopilotAgent Agent.
47
+
48
+ This is Agent Base class for AI Copilots.
49
+ """
50
+ def __init__(
51
+ self,
52
+ name: str = 'Agent',
53
+ llm: str = 'vertexai',
54
+ tools: list = None,
55
+ prompt_template: str = None,
56
+ **kwargs
57
+ ):
58
+ super().__init__(name, llm, tools, prompt_template, **kwargs)
59
+ if not tools:
60
+ tools = tooling
61
+ self.tools = [
62
+ PythonAstREPLTool(
63
+ name='python_repl_ast',
64
+ globals={},
65
+ locals={}
66
+ ),
67
+ ExecutablePythonREPLTool(
68
+ name='executable_python_repl_ast',
69
+ globals={},
70
+ locals={}
71
+ )
72
+ ] + list(tools)
73
+ self.prompt = self.get_prompt(
74
+ self.prompt_template
75
+ )
76
+ print('PROMPT > ', self.prompt)
77
+
78
+ @classmethod
79
+ def default_tools(cls) -> list:
80
+ # ZipCode API Toolkit
81
+ tools = []
82
+ zpt_tools = []
83
+ try:
84
+ zpt = ZipcodeAPIToolkit()
85
+ zpt_tools = zpt.get_tools()
86
+
87
+ except Exception as e:
88
+ print('ERROR LOADING ZIPCODE TOOLS')
89
+
90
+ try:
91
+ # wk1 = WikipediaTool()
92
+ # wk12 = WikidataTool()
93
+
94
+ g1 = GoogleSearchTool()
95
+ g2 = GoogleLocationFinder()
96
+
97
+ b = BingSearchTool()
98
+ d = DuckDuckGoSearchTool()
99
+ # ask = AskNewsTool()
100
+
101
+ yt = YouTubeSearchTool()
102
+ stackexchange = StackExchangeTool()
103
+ weather = OpenWeatherMapTool()
104
+
105
+ tools = [
106
+ # wk1,wk12,
107
+ g1, g2,
108
+ b, d, # ask,
109
+ yt,
110
+ weather,
111
+ stackexchange
112
+ ]
113
+
114
+ except Exception as e:
115
+ print('TOOL Error > ', e)
116
+
117
+ return tools