pbesa 2.1__py3-none-any.whl → 4.0.0__py3-none-any.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.
Files changed (75) hide show
  1. pbesa/__init__.py +4 -3
  2. pbesa/cognitive.py +475 -0
  3. pbesa/kernel/__init__.py +4 -6
  4. pbesa/kernel/adapter.py +165 -0
  5. pbesa/kernel/agent.py +558 -0
  6. pbesa/kernel/io/__init__.py +2 -2
  7. pbesa/kernel/io/system_file.py +38 -0
  8. pbesa/kernel/io/tcp_server.py +23 -0
  9. pbesa/kernel/util.py +217 -0
  10. pbesa/kernel/world.py +43 -0
  11. pbesa/mas.py +565 -0
  12. pbesa/remote/__init__.py +5 -0
  13. pbesa/remote/adm_listener.py +44 -0
  14. pbesa/{middleware/remote/AdmListenerHandler.py → remote/adm_listener_handler.py} +74 -57
  15. pbesa/remote/exceptions.py +18 -0
  16. pbesa/remote/remote_adm.py +42 -0
  17. pbesa/{middleware/remote/RemoteAdmHandler.py → remote/remote_adm_handler.py} +109 -83
  18. pbesa/social/__init__.py +4 -0
  19. pbesa/social/collaborative_team.py +299 -0
  20. pbesa/social/delegator.py +81 -0
  21. pbesa/social/delegator_team.py +334 -0
  22. pbesa/social/dialog.py +153 -0
  23. pbesa/social/dispatcher_team.py +319 -0
  24. pbesa/social/templates.py +18 -0
  25. pbesa/social/worker.py +188 -0
  26. {pbesa-2.1.dist-info → pbesa-4.0.0.dist-info}/LICENSE +21 -21
  27. {pbesa-2.1.dist-info → pbesa-4.0.0.dist-info}/LICENSE.txt +21 -21
  28. pbesa-4.0.0.dist-info/METADATA +8 -0
  29. pbesa-4.0.0.dist-info/RECORD +32 -0
  30. {pbesa-2.1.dist-info → pbesa-4.0.0.dist-info}/WHEEL +5 -5
  31. {pbesa-2.1.dist-info → pbesa-4.0.0.dist-info}/top_level.txt +0 -0
  32. pbesa/engine/__init__.py +0 -2
  33. pbesa/engine/bdi/BDIAg.py +0 -42
  34. pbesa/engine/bdi/BDILevel.py +0 -10
  35. pbesa/engine/bdi/BDIMachine.py +0 -116
  36. pbesa/engine/bdi/Goal.py +0 -28
  37. pbesa/engine/bdi/GoalExe.py +0 -36
  38. pbesa/engine/bdi/__init__.py +0 -5
  39. pbesa/engine/rational/ActionExe.py +0 -35
  40. pbesa/engine/rational/Brain.py +0 -10
  41. pbesa/engine/rational/RationalAg.py +0 -43
  42. pbesa/engine/rational/__init__.py +0 -3
  43. pbesa/kernel/adapter/Adapter.py +0 -26
  44. pbesa/kernel/adapter/FileAdapter.py +0 -23
  45. pbesa/kernel/adapter/__init__.py +0 -2
  46. pbesa/kernel/agent/Action.py +0 -19
  47. pbesa/kernel/agent/Agent.py +0 -91
  48. pbesa/kernel/agent/BehaviorExe.py +0 -33
  49. pbesa/kernel/agent/Channel.py +0 -10
  50. pbesa/kernel/agent/World.py +0 -15
  51. pbesa/kernel/agent/__init__.py +0 -5
  52. pbesa/kernel/io/SystemFile.py +0 -13
  53. pbesa/kernel/io/TCPServer.py +0 -4
  54. pbesa/kernel/system/Adm.py +0 -189
  55. pbesa/kernel/system/Directory.py +0 -36
  56. pbesa/kernel/system/__init__.py +0 -2
  57. pbesa/kernel/util/HashTable.py +0 -62
  58. pbesa/kernel/util/Queue.py +0 -231
  59. pbesa/kernel/util/__init__.py +0 -2
  60. pbesa/middleware/__init__.py +0 -3
  61. pbesa/middleware/adapter/GameAdapter.py +0 -64
  62. pbesa/middleware/adapter/MongoAdapter.py +0 -47
  63. pbesa/middleware/adapter/RESTAdapter.py +0 -52
  64. pbesa/middleware/adapter/SubProcessAdapter.py +0 -30
  65. pbesa/middleware/adapter/WSSAdapter.py +0 -89
  66. pbesa/middleware/adapter/WSSNJAdapter.py +0 -51
  67. pbesa/middleware/adapter/WSSNJHandler.py +0 -23
  68. pbesa/middleware/adapter/__init__.py +0 -7
  69. pbesa/middleware/remote/AdmListener.py +0 -17
  70. pbesa/middleware/remote/RemoteAdm.py +0 -17
  71. pbesa/middleware/remote/__init__.py +0 -4
  72. pbesa/middleware/web/WebAgTK.py +0 -15
  73. pbesa/middleware/web/__init__.py +0 -0
  74. pbesa-2.1.dist-info/METADATA +0 -25
  75. pbesa-2.1.dist-info/RECORD +0 -54
@@ -0,0 +1,334 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ ----------------------------------------------------------
4
+ -------------------------- PBESA -------------------------
5
+ ----------------------------------------------------------
6
+
7
+ @autor AKEN
8
+ @version 4.0.0
9
+ @date 09/08/24
10
+
11
+ The Delegator Team consists of one delegator and agents
12
+ working asynchronously to handle tasks. In this team, a
13
+ delegator transfers their responsibility to a specific
14
+ agent who then performs the task. The interaction with
15
+ the client is asynchronous, meaning the client does not
16
+ receive an immediate response. Agents are responsible for
17
+ modifying client resources, such as databases or webhooks,
18
+ making necessary updates or changes according to the
19
+ request.
20
+
21
+ This approach allows the delegator to focus on other
22
+ tasks while agents manage the modifications efficiently.
23
+ The Delegator Team is ideal for scenarios where the task
24
+ involves changes to specific resources and can be
25
+ carried out independently from the client interaction
26
+ process, enhancing team efficiency and flexibility.
27
+ """
28
+
29
+ # --------------------------------------------------------
30
+ # Define resources
31
+ # --------------------------------------------------------
32
+
33
+ from abc import abstractmethod
34
+ from .worker import Task, Worker
35
+ from ..kernel.agent import Queue
36
+ from ..kernel.agent import Agent
37
+ from ..kernel.agent import Action
38
+ from ..kernel.util import generate_short_uuid
39
+
40
+ # ----------------------------------------------------------
41
+ # Defines system component exceptions
42
+ # ----------------------------------------------------------
43
+
44
+ class DelegatorException(Exception):
45
+ """ Base class for exceptions of agent """
46
+ pass
47
+
48
+ # --------------------------------------------------------
49
+ # Define Delegate Action
50
+ # --------------------------------------------------------
51
+
52
+ class Delegate(Action):
53
+ """ An action is a response to the occurrence of an event """
54
+
55
+ def execute(self, data: any) -> None:
56
+ """
57
+ Response.
58
+ @param data Event data
59
+ """
60
+ ag = self.agent.get_free_queue().get()
61
+ self.agent.get_request_dict()[ag] = {
62
+ 'gateway': data['gateway'],
63
+ 'dtoList': []
64
+ }
65
+ self.adm.send_event(ag, 'task', data['dto'])
66
+
67
+ # --------------------------------------------------------
68
+ # Define DelegateAction
69
+ # --------------------------------------------------------
70
+
71
+ class DelegateAction(Action):
72
+ """ An action is a response to the occurrence of an event """
73
+
74
+ def execute(self, data: any) -> None:
75
+ """
76
+ Response.
77
+ @param data Event data
78
+ """
79
+ self.delegate(data)
80
+
81
+ def active_timeout(self, time: int) -> None:
82
+ """ Active timeout
83
+ @param time: Time
84
+ """
85
+ self.adm.send_event(self.agent.id, 'timeout', {'time': time, 'dto': None})
86
+
87
+ def to_assign(self, data: any) -> None:
88
+ """ Assign
89
+ @param data: Data
90
+ """
91
+ ag = self.agent.get_free_queue().get()
92
+ self.agent.get_request_dict()[ag] = {
93
+ 'dtoList': []
94
+ }
95
+ self.adm.send_event(ag, 'task', data)
96
+
97
+ @abstractmethod
98
+ def delegate(self, data: any) -> None:
99
+ """ Delegate
100
+ @param data: Data
101
+ """
102
+ pass
103
+
104
+ # --------------------------------------------------------
105
+ # Define Action
106
+ # --------------------------------------------------------
107
+
108
+ class NotifyFreeAction(Action):
109
+ """ An action is a response to the occurrence of an event """
110
+
111
+ def execute(self, data: any) -> None:
112
+ """
113
+ Response.
114
+ @param data Event data
115
+ """
116
+ self.agent.get_free_queue().put(data)
117
+
118
+ # --------------------------------------------------------
119
+ # Define Action
120
+ # --------------------------------------------------------
121
+
122
+ class ResponseAction(Action):
123
+ """ An action is a response to the occurrence of an event """
124
+
125
+ def send_response(self, request: dict) -> None:
126
+ """ Send response
127
+ @param request: Request
128
+ """
129
+ if len(request['dtoList']) == 1:
130
+ request['gateway'].put(request['dtoList'][0])
131
+ else:
132
+ request['gateway'].put(request['dtoList'])
133
+
134
+ def execute(self, data: dict) -> None:
135
+ """ Execute
136
+ @param data: Data
137
+ """
138
+ request = self.agent.get_request_dict()[data['source']]
139
+ if 'timeout' in data:
140
+ self.send_response(request)
141
+ else:
142
+ request['dtoList'].append(data['result'])
143
+ if len(request['dtoList']) >= self.agent.get_buffer_size():
144
+ self.send_response(request)
145
+
146
+ # --------------------------------------------------------
147
+ # Define component
148
+ # --------------------------------------------------------
149
+
150
+ class Delegator(Agent):
151
+ """ Represents the agent that delegates the execution of actions to other agents """
152
+
153
+ def __init__(self, agent_id:str, buffer_size:int, pool_size:int) -> None:
154
+ """ Constructor
155
+ @param agent_id: Agent ID
156
+ @param buffer_size: Buffer size
157
+ @param pool_size: Pool size
158
+ """
159
+ self.__type = type
160
+ self.__buffer_size = buffer_size
161
+ self.__request_dict = {}
162
+ self.__free_queue = Queue(pool_size)
163
+ self.__agent_list = []
164
+ super().__init__(agent_id)
165
+
166
+ def setup(self) -> None:
167
+ """ Set up method """
168
+ self._social = True
169
+ self.add_behavior('Delegate')
170
+ self.add_behavior('Notify')
171
+ self.bind_action('Notify', 'notify', NotifyFreeAction())
172
+ self.add_behavior('Response')
173
+ self.bind_action('Response', 'response', ResponseAction())
174
+ self.build()
175
+
176
+ def bind_delegate_action(self, action:Delegate) -> None:
177
+ """ Binds the delegate action to the agent
178
+ @param action: Delegate action
179
+ @raise PoolException: If the controller is a blocking type
180
+ """
181
+ self.bind_action('Delegate', 'delegate', action)
182
+
183
+ def suscribe_agent(self, agent:Agent) -> None:
184
+ """ Suscribes an agent to the controller
185
+ @param agent: Agent
186
+ """
187
+ self.__agent_list.append(agent.id)
188
+ agent.set_controller(self.id)
189
+ agent.set_controller_type('POOL')
190
+ self.__free_queue.put(agent.id)
191
+ actions = agent.get_actions()
192
+ for action in actions:
193
+ action.set_is_pool(True)
194
+ action.set_enable_response(False)
195
+
196
+ def suscribe_remote_agent(self, agent_id:str) -> None:
197
+ """ Suscribes an agent to the controller
198
+ @param agent_id: Agent ID
199
+ """
200
+ if not isinstance(agent_id, str):
201
+ raise DispatcherException('[Warn, suscribeRemoteAgent]: The object to subscribe is not an agent ID')
202
+ self.__agent_list.append(agent_id)
203
+ self.__free_queue.put(agent_id)
204
+
205
+ def broadcast_event(self, event:any, data:any) -> None:
206
+ """ Broadcasts an event to the agents
207
+ @param event: Event
208
+ @param data: Data
209
+ """
210
+ from pbesa.kernel.system.adm import Adm
211
+ for agent_id in self.__agent_list:
212
+ Adm().send_event(agent_id, event, data)
213
+
214
+ @abstractmethod
215
+ def build(self) -> None:
216
+ """ Builds the agent """
217
+ pass
218
+
219
+ def get_free_queue(self) -> Queue:
220
+ """ Gets the free queue
221
+ @return: Free queue
222
+ """
223
+ return self.__free_queue
224
+
225
+ def get_request_dict(self) -> dict:
226
+ """ Gets the request dictionary
227
+ @return: Request dictionary
228
+ """
229
+ return self.__request_dict
230
+
231
+ def get_buffer_size(self) -> int:
232
+ """ Gets the buffer size
233
+ @return: Buffer size
234
+ """
235
+ return self.__buffer_size
236
+
237
+ def is_block(self) -> bool:
238
+ """ Checks if the pool is blocking
239
+ @return: True if the pool is blocking, False otherwise
240
+ """
241
+ return False
242
+
243
+
244
+ # --------------------------------------------------------
245
+ # Builder Methods
246
+ # --------------------------------------------------------
247
+
248
+ # --------------------------------------------------------
249
+ # Define Dispacher Agent
250
+
251
+ class DelegatorAgent(Delegator):
252
+ """ Through a class the concept of agent is defined """
253
+
254
+ def __init__(self, agent_id:str, buffer_size:int, pool_size:int, delegate:DelegateAction) -> None:
255
+ """ Constructor
256
+ @param agent_id: Agent ID
257
+ @param buffer_size: Buffer size
258
+ @param pool_size: Pool size
259
+ @param delegate: Delegate action
260
+ """
261
+ # Assign an action to the behavior
262
+ self.__delegate = delegate
263
+ super().__init__(agent_id, buffer_size, pool_size)
264
+
265
+ def build(self):
266
+ """
267
+ Method that allows defining the structure and
268
+ resources of the agent
269
+ """
270
+ # Assign an action to the behavior
271
+ self.bind_delegate_action(self.__delegate)
272
+
273
+ def shutdown(self):
274
+ """ Method to free up the resources taken by the agent """
275
+ pass
276
+
277
+ # --------------------------------------------------------
278
+ # Define Worker Agent
279
+
280
+ class WorkerAgent(Worker):
281
+ """ Through a class the concept of agent is defined """
282
+
283
+ def __init__(self, agent_id:str, task:Task) -> None:
284
+ """ Constructor
285
+ @param agent_id: Agent ID
286
+ @param task: Task
287
+ """
288
+ self.__task = task
289
+ super().__init__(agent_id)
290
+
291
+ def build(self):
292
+ """
293
+ Method that allows defining the structure and
294
+ resources of the agent
295
+ """
296
+ # Assign an action to the behavior
297
+ self.bind_task(self.__task)
298
+
299
+ def shutdown(self):
300
+ """ Method to free up the resources taken by the agent """
301
+ pass
302
+
303
+ # --------------------------------------------------------
304
+ # Define build Method
305
+
306
+ def build_delegator(name_team:str, agent_count, task_class:Task, delegate_class:DelegateAction) -> Delegator:
307
+ """ Builds the delegator
308
+ @param name_team: Team name
309
+ @param agent_count: Agent count
310
+ @param task: Task
311
+ @param delegate: Delegate
312
+ @return: Delegator
313
+ """
314
+ # Define worker agent list
315
+ w_ag_list = []
316
+ # Iterate over the number of agents
317
+ for i in range(agent_count):
318
+ short_uuid = generate_short_uuid()
319
+ w_id = f"{name_team}-{i}-{short_uuid}"
320
+ # Create the agent
321
+ w_ag = WorkerAgent(w_id, task_class())
322
+ # Start the agent
323
+ w_ag.start()
324
+ # Add the agent to the list
325
+ w_ag_list.append(w_ag)
326
+ # Create the delegator
327
+ delegator = DelegatorAgent(name_team, 1, agent_count, delegate_class())
328
+ # Subscribe the agents to the delegator
329
+ for w_ag in w_ag_list:
330
+ delegator.suscribe_agent(w_ag)
331
+ # Start the delegator
332
+ delegator.start()
333
+ # Return the delegator
334
+ return delegator
pbesa/social/dialog.py ADDED
@@ -0,0 +1,153 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ ----------------------------------------------------------
4
+ -------------------------- PBESA -------------------------
5
+ ----------------------------------------------------------
6
+
7
+ @autor AKEN
8
+ @version 4.0.0
9
+ @date 05/02/25
10
+ """
11
+
12
+ # --------------------------------------------------------
13
+ # Define resources
14
+ # --------------------------------------------------------
15
+
16
+ import datetime
17
+ from .templates import AFIRMATIVE_RESPONSE, GET_DATE
18
+
19
+ #------------------------------------------
20
+ # Define enumeration with states of the
21
+ # dialog
22
+ #------------------------------------------
23
+
24
+ class DialogState:
25
+ """ Define the dialog states """
26
+ START = "start"
27
+ ASK_CONFIRMATION_NEGATIVE = "ask confirmation negative"
28
+ ASK_CONFIRMATION_POSITIVE = "ask confirmation_positive"
29
+ END = "end"
30
+
31
+ #------------------------------------------
32
+ # Define Node class
33
+ #------------------------------------------
34
+
35
+ class ActionNode:
36
+ """ Node class """
37
+
38
+ def __init__(self, owner, performative, action, is_terminal=False):
39
+ self.owner = owner
40
+ self.children = {}
41
+ self.action = action
42
+ self.is_terminal = is_terminal
43
+ self.performative = performative
44
+
45
+ def add_child(self, tag, node):
46
+ self.children[tag] = node
47
+
48
+ class DeclarativeNode:
49
+ """ Node class """
50
+
51
+ def __init__(self, owner, performative, text, is_terminal=False):
52
+ self.text = text
53
+ self.owner = owner
54
+ self.children = {}
55
+ self.is_terminal = is_terminal
56
+ self.performative = performative
57
+
58
+ def add_child(self, tag, node):
59
+ self.children[tag] = node
60
+
61
+ class TerminalNode:
62
+ """ Node class """
63
+
64
+ def __init__(self, owner, performative):
65
+ self.owner = owner
66
+ self.performative = performative
67
+
68
+ class Node:
69
+ """ Node class """
70
+
71
+ def __init__(self, owner, performative, text=None, action=None, is_terminal=False, is_expert=False, value={}):
72
+ self.text = text
73
+ self.owner = owner
74
+ self.value = value
75
+ self.children = {}
76
+ self.action = action
77
+ self.is_expert = is_expert
78
+ self.is_terminal = is_terminal
79
+ self.performative = performative
80
+
81
+ def add_child(self, tag, node):
82
+ self.children[tag] = node
83
+
84
+ def set_value(self, key, value):
85
+ self.value[key] = value
86
+
87
+ def run(self, dto):
88
+ if self.text and not self.action:
89
+ return self
90
+ elif self.action:
91
+ window = self.action(self, dto)
92
+ if window.is_terminal:
93
+ return window.action(window, dto) if window.action else window
94
+ elif self.is_expert:
95
+ return self
96
+ return window.run(dto)
97
+ raise Exception("Se ha estructurado mal el dialogo.")
98
+
99
+ def generate_response(self):
100
+ response = get_response_message()
101
+ response['text'] = self.text
102
+ if self.value:
103
+ for key, value in self.value.items():
104
+ response[key] = value
105
+ return response
106
+
107
+ #------------------------------------------
108
+ # Define functions
109
+ #------------------------------------------
110
+
111
+ def get_response_message():
112
+ """ Define the response message """
113
+ return {
114
+ "text": None,
115
+ "share": False
116
+ }
117
+
118
+ def check_yes(self, dto):
119
+ """ Check if text is yes """
120
+ user_response = dto['query']
121
+ user_response = user_response.lower()
122
+ if user_response == "si" or user_response == "sí" or user_response == "yes" or user_response == "s ":
123
+ return self.children['yes']
124
+ model_handler = self.owner.model_handler
125
+ prompt = AFIRMATIVE_RESPONSE % user_response
126
+ response = model_handler.make_request(prompt)
127
+ if response:
128
+ if "SI_ES" in response:
129
+ return self.children['yes']
130
+ return self.children['no']
131
+
132
+ def check_date(self, dto):
133
+ """ Check if date is valid """
134
+ date = dto['query']
135
+ session = dto['session']
136
+ model_handler = self.owner.model_handler
137
+ # Get current date in %d-%m-%Y format.
138
+ current_date = datetime.datetime.now().strftime("%d-%m-%Y")
139
+ date_prompt = GET_DATE
140
+ prompt = date_prompt.format(
141
+ fecha_actual= current_date,
142
+ texto= date
143
+ )
144
+ response = model_handler.make_request(prompt, engine="gpt-4")
145
+ # Check if response is valid date.
146
+ if response:
147
+ try:
148
+ reminder_date = datetime.datetime.strptime(response, '%Y-%m-%d %H:%M:%S')
149
+ dto['reminder_date'] = reminder_date
150
+ return self.children['yes']
151
+ except:
152
+ pass
153
+ return self.children['no']