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
@@ -0,0 +1,292 @@
1
+ from typing import List
2
+ from aiohttp import web
3
+ import pandas as pd
4
+ from navigator_auth.decorators import (
5
+ is_authenticated,
6
+ user_session
7
+ )
8
+ from navigator.views import BaseView
9
+ from querysource.queries.qs import QS
10
+ from querysource.queries.multi import MultiQS
11
+ from ..bots.abstract import AbstractBot
12
+ from ..llms.vertex import VertexLLM
13
+ from ..bots.data import PandasAgent
14
+ from ..models import AgentModel
15
+
16
+
17
+ @is_authenticated()
18
+ @user_session()
19
+ class AgentHandler(BaseView):
20
+ """
21
+ AgentHandler.
22
+ description: Agent Handler for Parrot Application.
23
+
24
+ TODO: Support for per-user session agents.
25
+ - Tool for doing an EDA (exploratory data-analysis) on a dataframe.
26
+ - Tool for doing a data profiling on a dataframe.
27
+ """
28
+ async def put(self, *args, **kwargs):
29
+ """
30
+ put.
31
+ description: Put method for AgentHandler
32
+
33
+ Use this method to create a new Agent.
34
+ """
35
+ app = self.request.app
36
+ _id = self.request.match_info.get('agent_name', None)
37
+ data = await self.request.json()
38
+ name = data.pop('name', None)
39
+ if not name:
40
+ return self.json_response(
41
+ {
42
+ "message": "Agent name not found."
43
+ },
44
+ status=404
45
+ )
46
+ _id = data.pop('chatbot_id', None)
47
+ # To create a new agent, we need:
48
+ # A list of queries (Query slugs) to be converted into dataframes
49
+ query = data.pop('query', None)
50
+ if not query:
51
+ return self.json_response(
52
+ {
53
+ "message": "No query was found."
54
+ },
55
+ status=400
56
+ )
57
+ # A list of tools to be used by the agent
58
+ tools = kwargs.pop('tools', [])
59
+ # a backstory and an optional capabilities for Bot.
60
+ backstory = data.pop('backstory', None)
61
+ capabilities = data.pop('capabilities', None)
62
+ try:
63
+ manager = app['bot_manager']
64
+ except KeyError:
65
+ return self.json_response(
66
+ {
67
+ "message": "Chatbot Manager is not installed."
68
+ },
69
+ status=404
70
+ )
71
+ if agent := manager.get_agent(_id):
72
+ args = {
73
+ "message": f"Agent {name} already exists.",
74
+ "agent": agent.name,
75
+ "agent_id": agent.chatbot_id,
76
+ "description": agent.description,
77
+ "backstory": agent.backstory,
78
+ "capabilities": agent.get_capabilities(),
79
+ "type": 'PandasAgent',
80
+ "llm": f"{agent.llm!r}",
81
+ "temperature": agent.llm.temperature,
82
+ }
83
+ return self.json_response(
84
+ args,
85
+ status=208
86
+ )
87
+ try:
88
+ # Generate the Data Frames from the queries:
89
+ dfs = await PandasAgent.gen_data(
90
+ query=query.copy(),
91
+ agent_name=_id,
92
+ refresh=True,
93
+ no_cache=True
94
+ )
95
+ except Exception as e:
96
+ return self.json_response(
97
+ {
98
+ "message": f"Error generating dataframes: {e}"
99
+ },
100
+ status=400
101
+ )
102
+ try:
103
+ args = {
104
+ "name": name,
105
+ "df": dfs,
106
+ "query": query,
107
+ "tools": tools,
108
+ "backstory": backstory,
109
+ "capabilities": capabilities,
110
+ **data
111
+ }
112
+ if _id:
113
+ args['chatbot_id'] = _id
114
+ # Create and Add the agent to the manager
115
+ agent = await manager.create_agent(
116
+ class_name=PandasAgent,
117
+ **args
118
+ )
119
+ await agent.configure(app=app)
120
+ except Exception as e:
121
+ return self.json_response(
122
+ {
123
+ "message": f"Error on Agent creation: {e}"
124
+ },
125
+ status=400
126
+ )
127
+ # Check if the agent was created successfully
128
+ if not agent:
129
+ return self.json_response(
130
+ {
131
+ "message": f"Error creating agent: {e}"
132
+ },
133
+ status=400
134
+ )
135
+ # Saving Agent into DB:
136
+ try:
137
+ args.pop('df')
138
+ args['query'] = query
139
+ result = await manager.save_agent(**args)
140
+ if not result:
141
+ manager.remove_agent(agent)
142
+ return self.json_response(
143
+ {
144
+ "message": f"Error saving agent {agent.name}"
145
+ },
146
+ status=400
147
+ )
148
+ except Exception as e:
149
+ manager.remove_agent(agent)
150
+ return self.json_response(
151
+ {
152
+ "message": f"Error saving agent {agent.name}: {e}"
153
+ },
154
+ status=400
155
+ )
156
+ # Return the agent information
157
+ return self.json_response(
158
+ {
159
+ "message": f"Agent {name} created successfully.",
160
+ "agent": agent.name,
161
+ "agent_id": agent.chatbot_id,
162
+ "description": agent.description,
163
+ "backstory": agent.backstory,
164
+ "capabilities": agent.get_capabilities(),
165
+ "type": 'PandasAgent',
166
+ "llm": f"{agent.llm!r}",
167
+ "temperature": agent.llm.temperature,
168
+ },
169
+ status=201
170
+ )
171
+
172
+ async def post(self, *args, **kwargs):
173
+ """
174
+ post.
175
+ description: Do a query to the Agent.
176
+ Use this method to interact with a Agent.
177
+ """
178
+ app = self.request.app
179
+ try:
180
+ manager = app['bot_manager']
181
+ except KeyError:
182
+ return self.json_response(
183
+ {
184
+ "message": "Chatbot Manager is not installed."
185
+ },
186
+ status=404
187
+ )
188
+ name = self.request.match_info.get('agent_name', None)
189
+ if not name:
190
+ return self.json_response(
191
+ {
192
+ "message": "Agent name not found."
193
+ },
194
+ status=404
195
+ )
196
+ data = await self.request.json()
197
+ if not 'query' in data:
198
+ return self.json_response(
199
+ {
200
+ "message": "No query was found."
201
+ },
202
+ status=400
203
+ )
204
+ if agent := manager.get_agent(name):
205
+ # doing a question to the agent:
206
+ try:
207
+ response, result = await agent.invoke(
208
+ data['query']
209
+ )
210
+ result.response = response
211
+ # null the chat_history:
212
+ result.chat_history = []
213
+ return self.json_response(response=result)
214
+ except Exception as e:
215
+ return self.json_response(
216
+ {
217
+ "message": f"Error invoking agent: {e}"
218
+ },
219
+ status=400
220
+ )
221
+ else:
222
+ return self.json_response(
223
+ {
224
+ "message": f"Agent {name} not found."
225
+ },
226
+ status=404
227
+ )
228
+
229
+ async def patch(self, *args, **kwargs):
230
+ """
231
+ patch.
232
+ description: Update the data of the Agent.
233
+ Use this method to update the dataframes assigned to the Agent.
234
+ """
235
+ app = self.request.app
236
+ try:
237
+ manager = app['bot_manager']
238
+ except KeyError:
239
+ return self.json_response(
240
+ {
241
+ "message": "Chatbot Manager is not installed."
242
+ },
243
+ status=404
244
+ )
245
+ name = self.request.match_info.get('agent_name', None)
246
+ if not name:
247
+ return self.json_response(
248
+ {
249
+ "message": "Agent name not found."
250
+ },
251
+ status=404
252
+ )
253
+ try:
254
+ data = await self.request.json()
255
+ except Exception as e:
256
+ data = {}
257
+ query = data.pop('query', None)
258
+ if agent := manager.get_agent(name):
259
+ # dextract the new query from the request, or from agent
260
+ qry = query if query else agent.get_query()
261
+ try:
262
+ # Generate the Data Frames from the queries:
263
+ dfs = await PandasAgent.gen_data(
264
+ agent_name=str(agent.chatbot_id),
265
+ query=qry,
266
+ refresh=True
267
+ )
268
+ if dfs:
269
+ # Update the agent with the new dataframes
270
+ agent.df = dfs
271
+ # Update the agent with the new query
272
+ await agent.configure(df=dfs)
273
+ return self.json_response(
274
+ {
275
+ "message": f"{agent.name}: Agent Data was Updated."
276
+ },
277
+ status=202
278
+ )
279
+ except Exception as e:
280
+ return self.json_response(
281
+ {
282
+ "message": f"Error refreshing agent {agent.name}: {e}"
283
+ },
284
+ status=400
285
+ )
286
+ else:
287
+ return self.json_response(
288
+ {
289
+ "message": f"Agent {name} not found."
290
+ },
291
+ status=404
292
+ )
@@ -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 = 'bigquery'
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)
@@ -0,0 +1,192 @@
1
+ from aiohttp import web
2
+ from navigator_auth.decorators import (
3
+ is_authenticated,
4
+ user_session,
5
+ allowed_organizations
6
+ )
7
+ from navigator.views import BaseView
8
+ from ..bots.abstract import AbstractBot
9
+
10
+
11
+ @is_authenticated()
12
+ @user_session()
13
+ class ChatHandler(BaseView):
14
+ """
15
+ ChatHandler.
16
+ description: Chat Handler for Parrot Application.
17
+ """
18
+
19
+ async def get(self, **kwargs):
20
+ """
21
+ get.
22
+ description: Get method for ChatHandler.
23
+ """
24
+ name = self.request.match_info.get('chatbot_name', None)
25
+ if not name:
26
+ return self.json_response({
27
+ "message": "Welcome to Parrot Chatbot Service."
28
+ })
29
+ else:
30
+ # retrieve chatbof information:
31
+ manager = self.request.app['bot_manager']
32
+ chatbot = manager.get_bot(name)
33
+ if not chatbot:
34
+ return self.error(
35
+ f"Chatbot {name} not found.",
36
+ status=404
37
+ )
38
+ config_file = getattr(chatbot, 'config_file', None)
39
+ return self.json_response({
40
+ "chatbot": chatbot.name,
41
+ "description": chatbot.description,
42
+ "role": chatbot.role,
43
+ "embedding_model": chatbot.embedding_model,
44
+ "llm": f"{chatbot.llm!r}",
45
+ "temperature": chatbot.llm.temperature,
46
+ "config_file": config_file
47
+ })
48
+
49
+ async def post(self, *args, **kwargs):
50
+ """
51
+ post.
52
+ description: Post method for ChatHandler.
53
+
54
+ Use this method to interact with a Chatbot.
55
+ """
56
+ app = self.request.app
57
+ name = self.request.match_info.get('chatbot_name', None)
58
+ qs = self.query_parameters(self.request)
59
+ data = await self.request.json()
60
+ if not 'query' in data:
61
+ return self.json_response(
62
+ {
63
+ "message": "No query was found."
64
+ },
65
+ status=400
66
+ )
67
+ if 'use_llm' in qs:
68
+ # passing another LLM to the Chatbot:
69
+ llm = qs.get('use_llm')
70
+ else:
71
+ llm = None
72
+ try:
73
+ manager = app['bot_manager']
74
+ except KeyError:
75
+ return self.json_response(
76
+ {
77
+ "message": "Chatbot Manager is not installed."
78
+ },
79
+ status=404
80
+ )
81
+ try:
82
+ chatbot: AbstractBot = manager.get_bot(name)
83
+ if not chatbot:
84
+ raise KeyError(
85
+ f"Chatbot {name} not found."
86
+ )
87
+ except (TypeError, KeyError):
88
+ return self.json_response(
89
+ {
90
+ "message": f"Chatbot {name} not found."
91
+ },
92
+ status=404
93
+ )
94
+ # getting the question:
95
+ question = data.pop('query')
96
+ try:
97
+ session = self.request.session
98
+ except AttributeError:
99
+ session = None
100
+ if not session:
101
+ return self.json_response(
102
+ {
103
+ "message": "User Session is required to interact with a Chatbot."
104
+ },
105
+ status=400
106
+ )
107
+ try:
108
+ async with chatbot.retrieval(request=self.request) as retrieval:
109
+ session_id = session.get('session_id', None)
110
+ memory_key = f'{session.session_id}_{name}_message_store'
111
+ memory = retrieval.get_memory(session_id=memory_key)
112
+ result = await retrieval.invoke(
113
+ question=question,
114
+ llm=llm,
115
+ memory=memory,
116
+ **data
117
+ )
118
+ # Drop "memory" information:
119
+ result.chat_history = None
120
+ if result.source_documents:
121
+ documents = []
122
+ for doc in result.source_documents:
123
+ dc = {
124
+ **doc.metadata
125
+ }
126
+ documents.append(dc)
127
+ result.source_documents = documents
128
+ return self.json_response(response=result)
129
+ except ValueError as exc:
130
+ return self.error(
131
+ f"{exc}",
132
+ exception=exc,
133
+ status=400
134
+ )
135
+ except web.HTTPException as exc:
136
+ return self.error(
137
+ f"{exc}",
138
+ exception=exc,
139
+ status=400
140
+ )
141
+ except Exception as exc:
142
+ return self.error(
143
+ f"Error invoking chatbot {name}: {exc}",
144
+ exception=exc,
145
+ status=400
146
+ )
147
+
148
+
149
+ @is_authenticated()
150
+ @user_session()
151
+ class BotHandler(BaseView):
152
+ """BotHandler.
153
+
154
+
155
+ Use this handler to interact with a brand new chatbot, consuming a configuration.
156
+ """
157
+ async def put(self):
158
+ """Create a New Bot (passing a configuration).
159
+ """
160
+ try:
161
+ manager = self.request.app['bot_manager']
162
+ except KeyError:
163
+ return self.json_response(
164
+ {
165
+ "message": "Chatbot Manager is not installed."
166
+ },
167
+ status=404
168
+ )
169
+ # TODO: Making a Validation of data
170
+ data = await self.request.json()
171
+ name = data.pop('name', None)
172
+ if not name:
173
+ return self.json_response(
174
+ {
175
+ "message": "Name for Bot Creation is required."
176
+ },
177
+ status=400
178
+ )
179
+ try:
180
+ chatbot = manager.create_chatbot(name=name, **data)
181
+ await chatbot.configure(name=name, app=self.request.app)
182
+ return self.json_response(
183
+ {
184
+ "message": f"Chatbot {name} created successfully."
185
+ }
186
+ )
187
+ except Exception as exc:
188
+ return self.error(
189
+ f"Error creating chatbot {name}: {exc}",
190
+ exception=exc,
191
+ status=400
192
+ )
@@ -0,0 +1,6 @@
1
+ from .database import DBInterface
2
+
3
+
4
+ __all__ = (
5
+ 'DBInterface',
6
+ )