ai-parrot 0.8.3__cp312-cp312-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.
- ai_parrot-0.8.3.dist-info/LICENSE +21 -0
- ai_parrot-0.8.3.dist-info/METADATA +306 -0
- ai_parrot-0.8.3.dist-info/RECORD +128 -0
- ai_parrot-0.8.3.dist-info/WHEEL +6 -0
- ai_parrot-0.8.3.dist-info/top_level.txt +2 -0
- parrot/__init__.py +30 -0
- parrot/bots/__init__.py +5 -0
- parrot/bots/abstract.py +1115 -0
- parrot/bots/agent.py +492 -0
- parrot/bots/basic.py +9 -0
- parrot/bots/bose.py +17 -0
- parrot/bots/chatbot.py +271 -0
- parrot/bots/cody.py +17 -0
- parrot/bots/copilot.py +117 -0
- parrot/bots/data.py +730 -0
- parrot/bots/dataframe.py +103 -0
- parrot/bots/hrbot.py +15 -0
- parrot/bots/interfaces/__init__.py +1 -0
- parrot/bots/interfaces/retrievers.py +12 -0
- parrot/bots/notebook.py +619 -0
- parrot/bots/odoo.py +17 -0
- parrot/bots/prompts/__init__.py +41 -0
- parrot/bots/prompts/agents.py +91 -0
- parrot/bots/prompts/data.py +214 -0
- parrot/bots/retrievals/__init__.py +1 -0
- parrot/bots/retrievals/constitutional.py +19 -0
- parrot/bots/retrievals/multi.py +122 -0
- parrot/bots/retrievals/retrieval.py +610 -0
- parrot/bots/tools/__init__.py +7 -0
- parrot/bots/tools/eda.py +325 -0
- parrot/bots/tools/pdf.py +50 -0
- parrot/bots/tools/plot.py +48 -0
- parrot/bots/troc.py +16 -0
- parrot/conf.py +170 -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-312-x86_64-linux-gnu.so +0 -0
- parrot/handlers/__init__.py +4 -0
- parrot/handlers/agents.py +292 -0
- parrot/handlers/bots.py +196 -0
- parrot/handlers/chat.py +192 -0
- parrot/interfaces/__init__.py +6 -0
- parrot/interfaces/database.py +27 -0
- parrot/interfaces/http.py +805 -0
- parrot/interfaces/images/__init__.py +0 -0
- parrot/interfaces/images/plugins/__init__.py +18 -0
- parrot/interfaces/images/plugins/abstract.py +58 -0
- parrot/interfaces/images/plugins/exif.py +709 -0
- parrot/interfaces/images/plugins/hash.py +52 -0
- parrot/interfaces/images/plugins/vision.py +104 -0
- parrot/interfaces/images/plugins/yolo.py +66 -0
- parrot/interfaces/images/plugins/zerodetect.py +197 -0
- parrot/llms/__init__.py +1 -0
- parrot/llms/abstract.py +69 -0
- parrot/llms/anthropic.py +58 -0
- parrot/llms/gemma.py +15 -0
- parrot/llms/google.py +44 -0
- parrot/llms/groq.py +67 -0
- parrot/llms/hf.py +45 -0
- parrot/llms/openai.py +61 -0
- parrot/llms/pipes.py +114 -0
- parrot/llms/vertex.py +89 -0
- parrot/loaders/__init__.py +9 -0
- parrot/loaders/abstract.py +628 -0
- parrot/loaders/files/__init__.py +0 -0
- parrot/loaders/files/abstract.py +39 -0
- parrot/loaders/files/text.py +63 -0
- parrot/loaders/txt.py +26 -0
- parrot/manager.py +333 -0
- parrot/models.py +504 -0
- parrot/py.typed +0 -0
- parrot/stores/__init__.py +11 -0
- parrot/stores/abstract.py +248 -0
- parrot/stores/chroma.py +188 -0
- parrot/stores/duck.py +162 -0
- parrot/stores/embeddings/__init__.py +10 -0
- parrot/stores/embeddings/abstract.py +46 -0
- parrot/stores/embeddings/base.py +52 -0
- parrot/stores/embeddings/bge.py +20 -0
- parrot/stores/embeddings/fastembed.py +17 -0
- parrot/stores/embeddings/google.py +18 -0
- parrot/stores/embeddings/huggingface.py +20 -0
- parrot/stores/embeddings/ollama.py +14 -0
- parrot/stores/embeddings/openai.py +26 -0
- parrot/stores/embeddings/transformers.py +21 -0
- parrot/stores/embeddings/vertexai.py +17 -0
- parrot/stores/empty.py +10 -0
- parrot/stores/faiss.py +160 -0
- parrot/stores/milvus.py +397 -0
- parrot/stores/postgres.py +653 -0
- parrot/stores/qdrant.py +170 -0
- parrot/tools/__init__.py +23 -0
- parrot/tools/abstract.py +68 -0
- parrot/tools/asknews.py +33 -0
- parrot/tools/basic.py +51 -0
- parrot/tools/bby.py +359 -0
- parrot/tools/bing.py +13 -0
- parrot/tools/docx.py +343 -0
- parrot/tools/duck.py +62 -0
- parrot/tools/execute.py +56 -0
- parrot/tools/gamma.py +28 -0
- parrot/tools/google.py +170 -0
- parrot/tools/gvoice.py +301 -0
- parrot/tools/results.py +278 -0
- parrot/tools/stack.py +27 -0
- parrot/tools/weather.py +70 -0
- parrot/tools/wikipedia.py +58 -0
- parrot/tools/zipcode.py +198 -0
- parrot/utils/__init__.py +2 -0
- parrot/utils/parsers/__init__.py +5 -0
- parrot/utils/parsers/toml.cpython-312-x86_64-linux-gnu.so +0 -0
- parrot/utils/toml.py +11 -0
- parrot/utils/types.cpython-312-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
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import aiofiles
|
|
2
|
+
from .abstract import FilePlugin
|
|
3
|
+
|
|
4
|
+
class TextFile(FilePlugin):
|
|
5
|
+
"""
|
|
6
|
+
A class to handle text files asynchronously.
|
|
7
|
+
"""
|
|
8
|
+
def __init__(self, path: str, encoding: str = 'utf-8'):
|
|
9
|
+
"""
|
|
10
|
+
Initialize the TextFile with a file path.
|
|
11
|
+
|
|
12
|
+
Args:
|
|
13
|
+
path: Path to the text file.
|
|
14
|
+
encoding: File encoding (default: utf-8)
|
|
15
|
+
"""
|
|
16
|
+
super().__init__()
|
|
17
|
+
self.path = path
|
|
18
|
+
self.encoding = encoding
|
|
19
|
+
self._file = None
|
|
20
|
+
|
|
21
|
+
async def open(self):
|
|
22
|
+
"""
|
|
23
|
+
Asynchronously open the text file.
|
|
24
|
+
"""
|
|
25
|
+
try:
|
|
26
|
+
self._file = await aiofiles.open(self.path, mode='r', encoding=self.encoding)
|
|
27
|
+
self.logger.debug(
|
|
28
|
+
f"Successfully opened file: {self.path}"
|
|
29
|
+
)
|
|
30
|
+
except Exception as e:
|
|
31
|
+
self.logger.error(f"Error opening file {self.path}: {str(e)}")
|
|
32
|
+
raise
|
|
33
|
+
|
|
34
|
+
async def close(self):
|
|
35
|
+
"""
|
|
36
|
+
Asynchronously close the text file.
|
|
37
|
+
"""
|
|
38
|
+
if self._file is not None:
|
|
39
|
+
try:
|
|
40
|
+
await self._file.close()
|
|
41
|
+
self.logger.debug(f"Successfully closed file: {self.path}")
|
|
42
|
+
except Exception as e:
|
|
43
|
+
self.logger.error(f"Error closing file {self.path}: {str(e)}")
|
|
44
|
+
raise
|
|
45
|
+
finally:
|
|
46
|
+
self._file = None
|
|
47
|
+
|
|
48
|
+
async def read(self) -> str:
|
|
49
|
+
"""
|
|
50
|
+
Asynchronously read the content of the text file.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
Content of the text file as a string.
|
|
54
|
+
"""
|
|
55
|
+
if self._file is None:
|
|
56
|
+
await self.open()
|
|
57
|
+
|
|
58
|
+
try:
|
|
59
|
+
content = await self._file.read()
|
|
60
|
+
return content
|
|
61
|
+
except Exception as e:
|
|
62
|
+
self.logger.error(f"Error reading file {self.path}: {str(e)}")
|
|
63
|
+
raise
|
parrot/loaders/txt.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from typing import List
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from .abstract import AbstractLoader
|
|
4
|
+
from .files.text import TextFile
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class TextLoader(AbstractLoader):
|
|
8
|
+
"""
|
|
9
|
+
Loader for Text-based Files.
|
|
10
|
+
"""
|
|
11
|
+
extensions: List[str] = ['.txt', '.text', '.md', '.markdown', '.rd']
|
|
12
|
+
|
|
13
|
+
async def _load(self, path: Path, **kwargs) -> list:
|
|
14
|
+
"""
|
|
15
|
+
Load a TXT file.
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
path (Path): The path to the TXT file.
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
list: A list of Langchain Documents.
|
|
22
|
+
"""
|
|
23
|
+
async with TextFile(path) as file:
|
|
24
|
+
content = await file.read()
|
|
25
|
+
return self.create_document(content, path)
|
|
26
|
+
return []
|
parrot/manager.py
ADDED
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Chatbot Manager.
|
|
3
|
+
|
|
4
|
+
Tool for instanciate, managing and interacting with Chatbot through APIs.
|
|
5
|
+
"""
|
|
6
|
+
from typing import Any, Dict, Type
|
|
7
|
+
from importlib import import_module
|
|
8
|
+
from aiohttp import web
|
|
9
|
+
from datamodel.exceptions import ValidationError
|
|
10
|
+
from navconfig.logging import logging
|
|
11
|
+
from asyncdb.exceptions import NoDataFound
|
|
12
|
+
from .bots.abstract import AbstractBot
|
|
13
|
+
from .bots.basic import BasicBot
|
|
14
|
+
from .bots.chatbot import Chatbot
|
|
15
|
+
from .bots.data import PandasAgent
|
|
16
|
+
from .handlers.chat import ChatHandler, BotHandler
|
|
17
|
+
from .handlers.agents import AgentHandler
|
|
18
|
+
from .handlers import ChatbotHandler
|
|
19
|
+
from .models import ChatbotModel, AgentModel
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class BotManager:
|
|
23
|
+
"""BotManager.
|
|
24
|
+
|
|
25
|
+
Manage Bots/Agents and interact with them through via aiohttp App.
|
|
26
|
+
Deploy and manage chatbots and agents using a RESTful API.
|
|
27
|
+
|
|
28
|
+
"""
|
|
29
|
+
app: web.Application = None
|
|
30
|
+
|
|
31
|
+
def __init__(self) -> None:
|
|
32
|
+
self.app = None
|
|
33
|
+
self._bots: Dict[str, AbstractBot] = {}
|
|
34
|
+
self._agents: Dict[str, AbstractBot] = {}
|
|
35
|
+
self.logger = logging.getLogger(
|
|
36
|
+
name='Parrot.Manager'
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
def get_bot_class(self, class_name: str) -> Type[AbstractBot]:
|
|
40
|
+
"""
|
|
41
|
+
Dynamically import a Bot class based on the class name
|
|
42
|
+
from the relative module '.bots'.
|
|
43
|
+
Args:
|
|
44
|
+
class_name (str): The name of the Bot class to be imported.
|
|
45
|
+
Returns:
|
|
46
|
+
Type[AbstractBot]: A Bot class derived from AbstractBot.
|
|
47
|
+
"""
|
|
48
|
+
module = import_module('.bots', __package__)
|
|
49
|
+
try:
|
|
50
|
+
return getattr(module, class_name)
|
|
51
|
+
except AttributeError:
|
|
52
|
+
raise ImportError(
|
|
53
|
+
f"No class named '{class_name}' found in the module 'bots'."
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
async def load_bots(self, app: web.Application) -> None:
|
|
57
|
+
"""Load all chatbots from DB."""
|
|
58
|
+
self.logger.info("Loading chatbots from DB...")
|
|
59
|
+
db = app['database']
|
|
60
|
+
async with await db.acquire() as conn:
|
|
61
|
+
ChatbotModel.Meta.connection = conn
|
|
62
|
+
try:
|
|
63
|
+
bots = await ChatbotModel.filter(enabled=True)
|
|
64
|
+
except Exception as e:
|
|
65
|
+
self.logger.error(
|
|
66
|
+
f"Failed to load chatbots from DB: {e}"
|
|
67
|
+
)
|
|
68
|
+
return
|
|
69
|
+
for bot in bots:
|
|
70
|
+
if bot.bot_type == 'chatbot':
|
|
71
|
+
self.logger.notice(
|
|
72
|
+
f"Loading chatbot '{bot.name}'..."
|
|
73
|
+
)
|
|
74
|
+
cls_name = bot.bot_class
|
|
75
|
+
if cls_name is None:
|
|
76
|
+
class_name = Chatbot
|
|
77
|
+
else:
|
|
78
|
+
class_name = self.get_bot_class(cls_name)
|
|
79
|
+
chatbot = class_name(
|
|
80
|
+
chatbot_id=bot.chatbot_id,
|
|
81
|
+
name=bot.name,
|
|
82
|
+
description=bot.description,
|
|
83
|
+
use_llm=bot.llm,
|
|
84
|
+
model_name=bot.model_name,
|
|
85
|
+
model_config=bot.model_config,
|
|
86
|
+
embedding_model=bot.embedding_model,
|
|
87
|
+
use_vectorstore=bot.vector_store,
|
|
88
|
+
vector_store=bot.database,
|
|
89
|
+
config_file=bot.config_file,
|
|
90
|
+
role=bot.role,
|
|
91
|
+
goal=bot.goal,
|
|
92
|
+
backstory=bot.backstory,
|
|
93
|
+
rationale=bot.rationale,
|
|
94
|
+
pre_instructions=bot.pre_instructions,
|
|
95
|
+
company_information=bot.company_information,
|
|
96
|
+
vector_info=bot.database,
|
|
97
|
+
permissions=bot.permissions,
|
|
98
|
+
attributes=bot.attributes,
|
|
99
|
+
)
|
|
100
|
+
try:
|
|
101
|
+
await chatbot.configure(
|
|
102
|
+
app=app
|
|
103
|
+
)
|
|
104
|
+
except ValidationError as e:
|
|
105
|
+
self.logger.error(
|
|
106
|
+
f"Invalid configuration for chatbot '{chatbot.name}': {e}"
|
|
107
|
+
)
|
|
108
|
+
except Exception as e:
|
|
109
|
+
self.logger.error(
|
|
110
|
+
f"Failed to configure Bot '{chatbot.name}': {e}"
|
|
111
|
+
)
|
|
112
|
+
elif bot.bot_type == 'agent':
|
|
113
|
+
self.logger.notice(
|
|
114
|
+
f"Unsupported kind of Agent '{bot.name}'..."
|
|
115
|
+
)
|
|
116
|
+
chatbot = None
|
|
117
|
+
if chatbot:
|
|
118
|
+
self.add_bot(chatbot)
|
|
119
|
+
self.logger.info(
|
|
120
|
+
":: Chatbots loaded successfully."
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
async def load_agents(self, app: web.Application) -> None:
|
|
124
|
+
"""Load all Agents from DB."""
|
|
125
|
+
self.logger.info("Loading Agents from DB...")
|
|
126
|
+
db = app['database']
|
|
127
|
+
async with await db.acquire() as conn:
|
|
128
|
+
AgentModel.Meta.connection = conn
|
|
129
|
+
try:
|
|
130
|
+
agents = await AgentModel.filter(enabled=True)
|
|
131
|
+
except Exception as e:
|
|
132
|
+
self.logger.error(
|
|
133
|
+
f"Failed to load Agents from DB: {e}"
|
|
134
|
+
)
|
|
135
|
+
return
|
|
136
|
+
for agent in agents:
|
|
137
|
+
cls_name = agent.agent_class
|
|
138
|
+
if cls_name is None:
|
|
139
|
+
class_name = PandasAgent
|
|
140
|
+
else:
|
|
141
|
+
class_name = self.get_bot_class(cls_name)
|
|
142
|
+
# Get the queries before agent creation.
|
|
143
|
+
try:
|
|
144
|
+
queries = await class_name.gen_data(
|
|
145
|
+
query=agent.query,
|
|
146
|
+
agent_name=agent.chatbot_id,
|
|
147
|
+
refresh=False
|
|
148
|
+
)
|
|
149
|
+
except ValueError as e:
|
|
150
|
+
self.logger.error(
|
|
151
|
+
f"Failed to load queries for Agent '{agent.name}': {e}"
|
|
152
|
+
)
|
|
153
|
+
continue
|
|
154
|
+
# then, create the Agent:
|
|
155
|
+
try:
|
|
156
|
+
chatbot = class_name(
|
|
157
|
+
chatbot_id=agent.chatbot_id,
|
|
158
|
+
name=agent.name,
|
|
159
|
+
df=queries,
|
|
160
|
+
query=agent.query,
|
|
161
|
+
description=agent.description,
|
|
162
|
+
use_llm=agent.llm,
|
|
163
|
+
model_name=agent.model_name,
|
|
164
|
+
temperature=agent.temperature,
|
|
165
|
+
tools=agent.tools,
|
|
166
|
+
model_config=agent.model_config,
|
|
167
|
+
role=agent.role,
|
|
168
|
+
goal=agent.goal,
|
|
169
|
+
backstory=agent.backstory,
|
|
170
|
+
rationale=agent.rationale,
|
|
171
|
+
permissions=agent.permissions,
|
|
172
|
+
attributes=agent.attributes,
|
|
173
|
+
capabilities=agent.capabilities,
|
|
174
|
+
)
|
|
175
|
+
except Exception as e:
|
|
176
|
+
self.logger.error(
|
|
177
|
+
f"Failed to configure Agent '{agent.name}': {e}"
|
|
178
|
+
)
|
|
179
|
+
if chatbot:
|
|
180
|
+
await chatbot.configure(
|
|
181
|
+
app=app
|
|
182
|
+
)
|
|
183
|
+
self.add_agent(chatbot)
|
|
184
|
+
self.logger.notice(
|
|
185
|
+
f"Loaded Agent '{agent.name}'..."
|
|
186
|
+
)
|
|
187
|
+
self.logger.info(
|
|
188
|
+
":: IA Agents were loaded successfully."
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
def create_bot(self, class_name: Any = None, name: str = None, **kwargs) -> AbstractBot:
|
|
192
|
+
"""Create a Bot and add it to the manager."""
|
|
193
|
+
if class_name is None:
|
|
194
|
+
class_name = Chatbot
|
|
195
|
+
chatbot = class_name(**kwargs)
|
|
196
|
+
chatbot.name = name
|
|
197
|
+
self.add_bot(chatbot)
|
|
198
|
+
if 'llm' in kwargs:
|
|
199
|
+
llm = kwargs['llm']
|
|
200
|
+
llm_name = llm.pop('name')
|
|
201
|
+
model = llm.pop('model')
|
|
202
|
+
llm = chatbot.load_llm(
|
|
203
|
+
llm_name, model=model, **llm
|
|
204
|
+
)
|
|
205
|
+
chatbot.llm = llm
|
|
206
|
+
return chatbot
|
|
207
|
+
|
|
208
|
+
def add_bot(self, bot: AbstractBot) -> None:
|
|
209
|
+
"""Add a Bot to the manager."""
|
|
210
|
+
self._bots[bot.name] = bot
|
|
211
|
+
|
|
212
|
+
def get_bot(self, name: str) -> AbstractBot:
|
|
213
|
+
"""Get a Bot by name."""
|
|
214
|
+
return self._bots.get(name)
|
|
215
|
+
|
|
216
|
+
def remove_bot(self, name: str) -> None:
|
|
217
|
+
"""Remove a Bot by name."""
|
|
218
|
+
del self._bots[name]
|
|
219
|
+
|
|
220
|
+
def get_bots(self) -> Dict[str, AbstractBot]:
|
|
221
|
+
"""Get all Bots declared on Manager."""
|
|
222
|
+
return self._bots
|
|
223
|
+
|
|
224
|
+
async def create_agent(self, class_name: Any = None, name: str = None, **kwargs) -> AbstractBot:
|
|
225
|
+
if class_name is None:
|
|
226
|
+
class_name = PandasAgent
|
|
227
|
+
agent = class_name(name=name, **kwargs)
|
|
228
|
+
self.add_agent(agent)
|
|
229
|
+
if 'llm' in kwargs:
|
|
230
|
+
llm = kwargs['llm']
|
|
231
|
+
llm_name = llm.pop('name')
|
|
232
|
+
model = llm.pop('model')
|
|
233
|
+
llm = agent.load_llm(
|
|
234
|
+
llm_name, model=model, **llm
|
|
235
|
+
)
|
|
236
|
+
agent.llm = llm
|
|
237
|
+
return agent
|
|
238
|
+
|
|
239
|
+
def add_agent(self, agent: AbstractBot) -> None:
|
|
240
|
+
"""Add a Agent to the manager."""
|
|
241
|
+
self._agents[str(agent.chatbot_id)] = agent
|
|
242
|
+
|
|
243
|
+
def get_agent(self, name: str) -> AbstractBot:
|
|
244
|
+
"""Get a Agent by ID."""
|
|
245
|
+
return self._agents.get(name)
|
|
246
|
+
|
|
247
|
+
def remove_agent(self, agent: AbstractBot) -> None:
|
|
248
|
+
"""Remove a Bot by name."""
|
|
249
|
+
del self._agents[str(agent.chatbot_id)]
|
|
250
|
+
|
|
251
|
+
async def save_agent(self, name: str, **kwargs) -> None:
|
|
252
|
+
"""Save a Agent to the DB."""
|
|
253
|
+
self.logger.info(f"Saving Agent {name} into DB ...")
|
|
254
|
+
db = self.app['database']
|
|
255
|
+
async with await db.acquire() as conn:
|
|
256
|
+
AgentModel.Meta.connection = conn
|
|
257
|
+
try:
|
|
258
|
+
try:
|
|
259
|
+
agent = await AgentModel.get(name=name)
|
|
260
|
+
except NoDataFound:
|
|
261
|
+
agent = None
|
|
262
|
+
if agent:
|
|
263
|
+
self.logger.info(f"Agent {name} already exists.")
|
|
264
|
+
for key, val in kwargs.items():
|
|
265
|
+
agent.set(key, val)
|
|
266
|
+
await agent.update()
|
|
267
|
+
self.logger.info(f"Agent {name} updated.")
|
|
268
|
+
else:
|
|
269
|
+
self.logger.info(f"Agent {name} not found. Creating new one.")
|
|
270
|
+
# Create a new Agent
|
|
271
|
+
new_agent = AgentModel(
|
|
272
|
+
name=name,
|
|
273
|
+
**kwargs
|
|
274
|
+
)
|
|
275
|
+
await new_agent.insert()
|
|
276
|
+
self.logger.info(f"Agent {name} saved into DB.")
|
|
277
|
+
return True
|
|
278
|
+
except Exception as e:
|
|
279
|
+
self.logger.error(
|
|
280
|
+
f"Failed to Create new Agent {name} from DB: {e}"
|
|
281
|
+
)
|
|
282
|
+
return None
|
|
283
|
+
|
|
284
|
+
def get_app(self) -> web.Application:
|
|
285
|
+
"""Get the app."""
|
|
286
|
+
if self.app is None:
|
|
287
|
+
raise RuntimeError("App is not set.")
|
|
288
|
+
return self.app
|
|
289
|
+
|
|
290
|
+
def setup(self, app: web.Application) -> web.Application:
|
|
291
|
+
if isinstance(app, web.Application):
|
|
292
|
+
self.app = app # register the app into the Extension
|
|
293
|
+
else:
|
|
294
|
+
self.app = app.get_app() # Nav Application
|
|
295
|
+
# register signals for startup and shutdown
|
|
296
|
+
self.app.on_startup.append(self.on_startup)
|
|
297
|
+
self.app.on_shutdown.append(self.on_shutdown)
|
|
298
|
+
# Add Manager to main Application:
|
|
299
|
+
self.app['bot_manager'] = self
|
|
300
|
+
## Configure Routes
|
|
301
|
+
router = self.app.router
|
|
302
|
+
# Chat Information Router
|
|
303
|
+
router.add_view(
|
|
304
|
+
'/api/v1/chats',
|
|
305
|
+
ChatHandler
|
|
306
|
+
)
|
|
307
|
+
router.add_view(
|
|
308
|
+
'/api/v1/chat/{chatbot_name}',
|
|
309
|
+
ChatHandler
|
|
310
|
+
)
|
|
311
|
+
# Agent Handler:
|
|
312
|
+
router.add_view(
|
|
313
|
+
'/api/v1/agent',
|
|
314
|
+
AgentHandler
|
|
315
|
+
)
|
|
316
|
+
router.add_view(
|
|
317
|
+
'/api/v1/agent/{agent_name}',
|
|
318
|
+
AgentHandler
|
|
319
|
+
)
|
|
320
|
+
# ChatBot Manager
|
|
321
|
+
ChatbotHandler.configure(self.app, '/api/v1/bots')
|
|
322
|
+
return self.app
|
|
323
|
+
|
|
324
|
+
async def on_startup(self, app: web.Application) -> None:
|
|
325
|
+
"""On startup."""
|
|
326
|
+
# configure all pre-configured chatbots:
|
|
327
|
+
await self.load_bots(app)
|
|
328
|
+
# configure all pre-configured agents:
|
|
329
|
+
await self.load_agents(app)
|
|
330
|
+
|
|
331
|
+
async def on_shutdown(self, app: web.Application) -> None:
|
|
332
|
+
"""On shutdown."""
|
|
333
|
+
pass
|