pbesa 4.0.9__tar.gz → 4.0.11__tar.gz

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 (114) hide show
  1. pbesa-4.0.11/PKG-INFO +13 -0
  2. pbesa-4.0.11/pbesa/celulas/celula_datos_identificables.py +53 -0
  3. pbesa-4.0.11/pbesa/celulas/celula_generar_documento.py +44 -0
  4. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/cognitive.py +115 -30
  5. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/social/dispatcher_team.py +177 -0
  6. pbesa-4.0.11/pbesa.egg-info/PKG-INFO +13 -0
  7. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa.egg-info/SOURCES.txt +2 -0
  8. pbesa-4.0.11/pbesa.egg-info/requires.txt +7 -0
  9. pbesa-4.0.11/setup.py +18 -0
  10. pbesa-4.0.9/PKG-INFO +0 -11
  11. pbesa-4.0.9/pbesa.egg-info/PKG-INFO +0 -11
  12. pbesa-4.0.9/pbesa.egg-info/requires.txt +0 -5
  13. pbesa-4.0.9/setup.py +0 -16
  14. {pbesa-4.0.9 → pbesa-4.0.11}/.gitignore +0 -0
  15. {pbesa-4.0.9 → pbesa-4.0.11}/LICENSE +0 -0
  16. {pbesa-4.0.9 → pbesa-4.0.11}/LICENSE.txt +0 -0
  17. {pbesa-4.0.9 → pbesa-4.0.11}/MANIFEST +0 -0
  18. {pbesa-4.0.9 → pbesa-4.0.11}/README.md +0 -0
  19. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/db.sqlite3 +0 -0
  20. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/helloworld/__init__.py +0 -0
  21. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/helloworld/__pycache__/__init__.cpython-36.pyc +0 -0
  22. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/helloworld/__pycache__/pbesa.cpython-36.pyc +0 -0
  23. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/helloworld/__pycache__/settings.cpython-36.pyc +0 -0
  24. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/helloworld/__pycache__/urls.cpython-36.pyc +0 -0
  25. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/helloworld/__pycache__/wsgi.cpython-36.pyc +0 -0
  26. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/helloworld/asgi.py +0 -0
  27. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/helloworld/pbesa.py +0 -0
  28. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/helloworld/settings.py +0 -0
  29. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/helloworld/urls.py +0 -0
  30. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/helloworld/wsgi.py +0 -0
  31. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/manage.py +0 -0
  32. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/translate/__init__.py +0 -0
  33. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/translate/__pycache__/__init__.cpython-36.pyc +0 -0
  34. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/translate/__pycache__/admin.cpython-36.pyc +0 -0
  35. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/translate/__pycache__/apps.cpython-36.pyc +0 -0
  36. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/translate/__pycache__/models.cpython-36.pyc +0 -0
  37. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/translate/__pycache__/urls.cpython-36.pyc +0 -0
  38. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/translate/__pycache__/views.cpython-36.pyc +0 -0
  39. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/translate/admin.py +0 -0
  40. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/translate/apps.py +0 -0
  41. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/translate/mas/controller/__pycache__/translatecontroller.cpython-36.pyc +0 -0
  42. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/translate/mas/controller/__pycache__/translatedelegate.cpython-36.pyc +0 -0
  43. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/translate/mas/controller/__pycache__/translateresponse.cpython-36.pyc +0 -0
  44. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/translate/mas/controller/translatecontroller.py +0 -0
  45. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/translate/mas/controller/translatedelegate.py +0 -0
  46. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/translate/mas/controller/translateresponse.py +0 -0
  47. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/translate/mas/worker/__pycache__/translatetask.cpython-36.pyc +0 -0
  48. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/translate/mas/worker/__pycache__/workeragent.cpython-36.pyc +0 -0
  49. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/translate/mas/worker/translatetask.py +0 -0
  50. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/translate/mas/worker/workeragent.py +0 -0
  51. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/translate/migrations/__init__.py +0 -0
  52. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/translate/migrations/__pycache__/__init__.cpython-36.pyc +0 -0
  53. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/translate/models.py +0 -0
  54. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/translate/tests.py +0 -0
  55. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/translate/urls.py +0 -0
  56. {pbesa-4.0.9 → pbesa-4.0.11}/examples/django/helloworld/translate/views.py +0 -0
  57. {pbesa-4.0.9 → pbesa-4.0.11}/examples/remote/mas/controller/__pycache__/countercontroller.cpython-36.pyc +0 -0
  58. {pbesa-4.0.9 → pbesa-4.0.11}/examples/remote/mas/controller/__pycache__/counterdelegate.cpython-36.pyc +0 -0
  59. {pbesa-4.0.9 → pbesa-4.0.11}/examples/remote/mas/controller/__pycache__/counterresponse.cpython-36.pyc +0 -0
  60. {pbesa-4.0.9 → pbesa-4.0.11}/examples/remote/mas/controller/__pycache__/translatecontroller.cpython-36.pyc +0 -0
  61. {pbesa-4.0.9 → pbesa-4.0.11}/examples/remote/mas/controller/__pycache__/translatedelegate.cpython-36.pyc +0 -0
  62. {pbesa-4.0.9 → pbesa-4.0.11}/examples/remote/mas/controller/__pycache__/translateresponse.cpython-36.pyc +0 -0
  63. {pbesa-4.0.9 → pbesa-4.0.11}/examples/remote/mas/controller/countercontroller.py +0 -0
  64. {pbesa-4.0.9 → pbesa-4.0.11}/examples/remote/mas/controller/counterdelegate.py +0 -0
  65. {pbesa-4.0.9 → pbesa-4.0.11}/examples/remote/mas/controller/counterresponse.py +0 -0
  66. {pbesa-4.0.9 → pbesa-4.0.11}/examples/remote/mas/worker/__pycache__/counteragent.cpython-36.pyc +0 -0
  67. {pbesa-4.0.9 → pbesa-4.0.11}/examples/remote/mas/worker/__pycache__/countertask.cpython-36.pyc +0 -0
  68. {pbesa-4.0.9 → pbesa-4.0.11}/examples/remote/mas/worker/__pycache__/translatetask.cpython-36.pyc +0 -0
  69. {pbesa-4.0.9 → pbesa-4.0.11}/examples/remote/mas/worker/__pycache__/workeragent.cpython-36.pyc +0 -0
  70. {pbesa-4.0.9 → pbesa-4.0.11}/examples/remote/mas/worker/counteragent.py +0 -0
  71. {pbesa-4.0.9 → pbesa-4.0.11}/examples/remote/mas/worker/countertask.py +0 -0
  72. {pbesa-4.0.9 → pbesa-4.0.11}/examples/remote/remote_a.py +0 -0
  73. {pbesa-4.0.9 → pbesa-4.0.11}/examples/remote/remote_b.py +0 -0
  74. {pbesa-4.0.9 → pbesa-4.0.11}/examples/remote/remote_c.py +0 -0
  75. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/__init__.py +0 -0
  76. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/celulas/__init__.py +0 -0
  77. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/celulas/celula_casos.py +0 -0
  78. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/celulas/celula_consultas.py +0 -0
  79. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/celulas/celula_saludos.py +0 -0
  80. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/celulas/web.py +0 -0
  81. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/kernel/__init__.py +0 -0
  82. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/kernel/adapter.py +0 -0
  83. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/kernel/agent.py +0 -0
  84. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/kernel/io/__init__.py +0 -0
  85. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/kernel/io/system_file.py +0 -0
  86. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/kernel/io/tcp_server.py +0 -0
  87. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/kernel/res/__init__.py +0 -0
  88. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/kernel/res/__pycache__/__init__.cpython-36.pyc +0 -0
  89. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/kernel/res/__pycache__/__init__.cpython-37.pyc +0 -0
  90. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/kernel/res/__pycache__/__init__.cpython-38.pyc +0 -0
  91. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/kernel/res/__pycache__/__init__.cpython-39.pyc +0 -0
  92. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/kernel/res/conf.json +0 -0
  93. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/kernel/util.py +0 -0
  94. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/kernel/world.py +0 -0
  95. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/mas.py +0 -0
  96. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/models.py +0 -0
  97. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/remote/__init__.py +0 -0
  98. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/remote/adm_listener.py +0 -0
  99. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/remote/adm_listener_handler.py +0 -0
  100. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/remote/exceptions.py +0 -0
  101. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/remote/remote_adm.py +0 -0
  102. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/remote/remote_adm_handler.py +0 -0
  103. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/social/__init__.py +0 -0
  104. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/social/collaborative_team.py +0 -0
  105. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/social/delegator.py +0 -0
  106. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/social/delegator_team.py +0 -0
  107. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/social/dialog.py +0 -0
  108. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/social/prompts.py +0 -0
  109. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/social/selected_dispatcher_team.py +0 -0
  110. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/social/templates.py +0 -0
  111. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa/social/worker.py +0 -0
  112. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa.egg-info/dependency_links.txt +0 -0
  113. {pbesa-4.0.9 → pbesa-4.0.11}/pbesa.egg-info/top_level.txt +0 -0
  114. {pbesa-4.0.9 → pbesa-4.0.11}/setup.cfg +0 -0
pbesa-4.0.11/PKG-INFO ADDED
@@ -0,0 +1,13 @@
1
+ Metadata-Version: 2.2
2
+ Name: pbesa
3
+ Version: 4.0.11
4
+ License-File: LICENSE
5
+ License-File: LICENSE.txt
6
+ Requires-Dist: pymongo>=4.6.3
7
+ Requires-Dist: requests>=2.32.3
8
+ Requires-Dist: azure-ai-projects>=1.0.0b6
9
+ Requires-Dist: azure-ai-inference>=1.0.0b9
10
+ Requires-Dist: azure-identity>=1.21.0
11
+ Requires-Dist: pandas>=2.2.3
12
+ Requires-Dist: scikit-learn>=1.6.1
13
+ Dynamic: requires-dist
@@ -0,0 +1,53 @@
1
+ import logging
2
+
3
+ PROMPT = """
4
+ Eres un clasificador de datos. Tu tarea es clasificar si el siguiente texto contiene **datos personales** o **datos identificables de una entidad**.
5
+
6
+ Responde únicamente con:
7
+ - CONTIENE_DATOS
8
+ - NO_CONTIENE_DATOS
9
+
10
+ **Se considera que el texto CONTIENE_DATOS si incluye:**
11
+ - Nombres completos de personas
12
+ - Razón social o nombre de una empresa
13
+ - Números de documento (cédula, NIT, etc.)
14
+ - Direcciones físicas (calle, carrera, avenida, etc.)
15
+ - Teléfonos o celulares
16
+ - Correos electrónicos
17
+
18
+ ---
19
+
20
+ **Ejemplos:**
21
+
22
+ 1. "Mi nombre es Carlos Ramírez y mi cédula es 1032478992." → CONTIENE_DATOS
23
+ 2. "Quiero demandar a la empresa Alimentos S.A.S. ubicada en la Calle 45 #10-20." → CONTIENE_DATOS
24
+ 3. "Puedes contactarme al correo johana.perez@gmail.com o al 3105678901." → CONTIENE_DATOS
25
+ 4. "Necesito información sobre cómo presentar una queja." → NO_CONTIENE_DATOS
26
+ 5. "Hola, buen día" → NO_CONTIENE_DATOS
27
+ 6. "La empresa Agropecuaria S.A. está usando marcas similares a las nuestras." → CONTIENE_DATOS
28
+ 7. "¿Cuál es el procedimiento para radicar una solicitud?" → NO_CONTIENE_DATOS
29
+
30
+ ---
31
+
32
+ Texto: "%s"
33
+
34
+ Clasificación:
35
+ """
36
+
37
+ # Efectua la inferencia del modelo.
38
+ def derive(service, text) -> any:
39
+ try:
40
+ tmp_work_memory = []
41
+ prompt = PROMPT % text
42
+ tmp_work_memory.append({"role": "user", "content": prompt})
43
+ res = service.generate(tmp_work_memory)
44
+ logging.info(f"Procesando: {text}")
45
+ logging.info(f"Respuesta: {res}")
46
+ if not res or res == "":
47
+ res = text
48
+ logging.warning(f"No obtener una respuesta.")
49
+ return res
50
+ except Exception as e:
51
+ logging.error(f"Error al procesar: {text}")
52
+ logging.error(e)
53
+ return None
@@ -0,0 +1,44 @@
1
+ import logging
2
+
3
+ PROMPT = """
4
+ Eres un asistente jurídico experto. Tu tarea es **extraer los datos** y generar el documento siguiendo una plantilla predefinida.
5
+
6
+ Recibirás un texto que incluye:
7
+ - Un relato de hechos sobre una posible infracción
8
+ - Datos personales del demandante y del demandado (pueden venir con nombre de campo o en texto libre)
9
+ - Información de contacto
10
+ - Algunas veces: el nombre de la entidad ante la cual se presenta la demanda
11
+
12
+ Usa el siguiente formato para estructurar tu respuesta. Si hay datos que no se encuentran, déjalos como estan en el formato.
13
+
14
+ ---
15
+
16
+ %s
17
+
18
+ ---
19
+
20
+ TEXTO DE ENTRADA:
21
+ %s
22
+
23
+ ---
24
+
25
+ DEMANDA FORMATEADA:
26
+ """
27
+
28
+ # Efectua la inferencia del modelo.
29
+ def derive(service, formato, text) -> any:
30
+ try:
31
+ logging.info(f"Procesando: {text}")
32
+ tmp_work_memory = []
33
+ prompt = PROMPT % (formato, text)
34
+ tmp_work_memory.append({"role": "user", "content": prompt})
35
+ res = service.generate(tmp_work_memory)
36
+ logging.info(f"Respuesta: {res}")
37
+ if not res or res == "":
38
+ res = text
39
+ logging.warning(f"No obtener una respuesta.")
40
+ return res
41
+ except Exception as e:
42
+ logging.error(f"Error al procesar: {text}")
43
+ logging.error(e)
44
+ return None
@@ -21,11 +21,12 @@ from .mas import Adm
21
21
  from pydantic import BaseModel
22
22
  from typing import List, Optional
23
23
  from abc import ABC, abstractmethod
24
- from .celulas import celula_casos, celula_consultas, celula_saludos
25
24
  from pbesa.models import AIFoundry, AzureInference, GPTService, ServiceProvider
26
25
  from pbesa.social.dialog import (
27
26
  DialogState, imprimir_grafo, recorrer_interacciones, extraer_diccionario_nodos,
28
- ActionNode, DeclarativeNode, GotoNode) #, TerminalNode
27
+ ActionNode, DeclarativeNode, GotoNode)
28
+ from .celulas import (celula_casos, celula_consultas, celula_saludos, celula_datos_identificables,
29
+ celula_generar_documento)
29
30
  from pbesa.social.prompts import CLASSIFICATION_PROMPT, DERIVE_PROMPT, RECOVERY_PROMPT, ADAPT_PROMPT
30
31
  # --------------------------------------------------------
31
32
  # Define DTOs
@@ -36,6 +37,7 @@ class InteraccionDTO(BaseModel):
36
37
  tipo: str
37
38
  texto: str
38
39
  actor: str
40
+ isExpanded: Optional[bool] = None
39
41
  equipo: Optional[str] = None
40
42
  herramienta: Optional[str] = None
41
43
  interacciones: List["InteraccionDTO"] = []
@@ -239,7 +241,8 @@ class AugmentedGeneration(ABC):
239
241
  # Define role
240
242
  self.__work_memory.append({"role": "user", "content": self.__role.objective})
241
243
  self.__work_memory.append({"role": "user", "content": self.__role.arquetype})
242
- self.__work_memory.append({"role": "user", "content": self.__role.example})
244
+ if self.__role.example:
245
+ self.__work_memory.append({"role": "user", "content": self.__role.example})
243
246
 
244
247
  def load_metadata(self, agent_metadata:AgentMetadata) -> None:
245
248
  """ Load metadata method
@@ -273,6 +276,45 @@ class AugmentedGeneration(ABC):
273
276
  # Set up model
274
277
  self.setup_world()
275
278
 
279
+ def command_derive(self, command, query) -> str | None:
280
+ try:
281
+ if command == "DATA_TYPE":
282
+ return celula_datos_identificables.derive(self.__ai_service, query)
283
+ elif command == "GENERATE_DOCUMENT":
284
+ return celula_generar_documento.derive(self.__ai_service, query["template"], query["text"])
285
+ return None
286
+ except Exception as e:
287
+ traceback.print_exc()
288
+ return None
289
+
290
+ def get_text(self, mensaje) -> str:
291
+ if mensaje:
292
+ mensaje_limpio = mensaje.replace("<|im_start|>user<|im_sep|>", "").replace("<|im_start|>system<|im_sep|>", "") \
293
+ .replace("<|im_start|>", "").replace("<|im_sep|>", "").replace("<|im_end|>", "") \
294
+ .replace("[Usuario]: ", "").replace("[Sistema]: ", "") \
295
+ .replace("<|user|>", "").replace("<|system|>", "")
296
+ return mensaje_limpio.strip()
297
+ else:
298
+ return ""
299
+
300
+ def custom_derive(self, instructions, prompt) -> str:
301
+ """ Generate method
302
+ :return: str
303
+ """
304
+ try:
305
+ instantane_memory = self.__work_memory.copy()
306
+ instantane_memory.append({"role": "user", "content": instructions})
307
+ instantane_memory.append({"role": "user", "content": prompt})
308
+ text = self.__ai_service.generate(instantane_memory)
309
+ text = self.get_text(text)
310
+ logging.info(f"Thought: {text}")
311
+ return text
312
+ except Exception as e:
313
+ traceback.print_exc()
314
+ logging.info(f"------------RESET---------------")
315
+ self.reset()
316
+ return "Lo lamento, no puedo responder en este momento"
317
+
276
318
  def derive(self, query) -> str:
277
319
  """ Generate method
278
320
  :return: str
@@ -282,21 +324,18 @@ class AugmentedGeneration(ABC):
282
324
  prompt = DERIVE_PROMPT % (content, query)
283
325
  instantane_memory = self.__work_memory.copy()
284
326
  instantane_memory.append({"role": "user", "content": prompt})
327
+ logging.info("")
328
+ logging.info("----- MEMORY -----")
329
+ logging.info("\n%s", json.dumps(instantane_memory, indent=4))
330
+ logging.info("-------------------")
331
+ logging.info("")
285
332
  text = self.__ai_service.generate(instantane_memory)
286
- logging.info(f"Thought: {text}")
287
- if self.__def_tool_dict:
288
- tool = self.__def_tool_dict.get(self.__role.tool)
289
- if tool:
290
- text = tool(text)
291
- else:
292
- text = "No se ha encontrado la herramienta"
333
+ text = self.get_text(text)
293
334
  return text
294
335
  except Exception as e:
295
336
  traceback.print_exc()
296
-
297
337
  logging.info(f"------------RESET---------------")
298
338
  self.reset()
299
-
300
339
  return "Lo lamento, no puedo responder en este momento"
301
340
 
302
341
  def get_role(self) -> Role:
@@ -305,6 +344,12 @@ class AugmentedGeneration(ABC):
305
344
  """
306
345
  return self.__role
307
346
 
347
+ def get_tool_dict(self):
348
+ """ Get tool dict method
349
+ :return: dict
350
+ """
351
+ return self.__def_tool_dict
352
+
308
353
  @abstractmethod
309
354
  def retrieval(self, query) -> str:
310
355
  """ Set retrieval method
@@ -320,6 +365,25 @@ class AugmentedGeneration(ABC):
320
365
  """
321
366
  pass
322
367
 
368
+ # --------------------------------------------------------
369
+ # Define Agent Tool component
370
+ # --------------------------------------------------------
371
+
372
+ class AgentTool(ABC):
373
+ """ Agent Tool class """
374
+
375
+ def __init__(self, agent) -> None:
376
+ """ Constructor method """
377
+ self.agent = agent
378
+
379
+ @abstractmethod
380
+ def tool(self, request: dict) -> None:
381
+ """ Tool method
382
+ :param request: request
383
+ :return: None
384
+ """
385
+ pass
386
+
323
387
  # --------------------------------------------------------
324
388
  # Define Rational component
325
389
  # --------------------------------------------------------
@@ -701,7 +765,7 @@ class Dialog(ABC):
701
765
  "performative": dialog_state,
702
766
  "counter": counter
703
767
  }
704
- logging.info(f"Recovery attemps: {self.__recovery["counter"]}")
768
+ logging.info(f"Recovery attemps: {self.__recovery['counter']}")
705
769
  # Verifica si se ha alcanzado el límite de recuperación
706
770
  if self.__recovery['counter'] <= 3 and self.__visited_nodes <= 3:
707
771
  select_node = None
@@ -717,13 +781,15 @@ class Dialog(ABC):
717
781
  consulta = celula_consultas.derive(self.__ai_service, query)
718
782
  saludo = celula_saludos.derive(self.__ai_service, query)
719
783
  # Verifica si es un saludo
720
- es_saludo = saludo == "SALUDO" and consulta == "NO_PREGUNTA" and caso == "NO_QUEJA_DEMANDA"
721
- es_consulta = consulta == "PREGUNTA_O_SOLICITUD" and caso == "NO_QUEJA_DEMANDA" and saludo == "NO_SALUDO"
722
- es_caso = caso == "QUEJA_DEMANDA" and consulta == "NO_PREGUNTA" and saludo == "NO_SALUDO"
784
+ es_saludo = ("SALUDO" in saludo) and ("NO_PREGUNTA" in consulta) and ("NO_QUEJA_DEMANDA" in caso) and not ("NO_SALUDO" in saludo)
785
+ es_consulta = ("PREGUNTA_O_SOLICITUD" in consulta) and ("NO_QUEJA_DEMANDA" in caso) and ("NO_SALUDO" in saludo) and not ("NO_PREGUNTA" in consulta)
786
+ es_caso = ("QUEJA_DEMANDA" in caso) and ("NO_PREGUNTA" in consulta) and ("NO_SALUDO" in saludo) and not ("NO_QUEJA_DEMANDA" in caso)
787
+ logging.info(f"==> Saludo: {saludo}, Consulta: {consulta}, Caso: {caso}")
788
+ logging.info(f"==> Es saludo: {es_saludo}, Es consulta: {es_consulta}, Es caso: {es_caso}")
723
789
  # Verifica los casos
724
790
  dicriminador = "Ninguno"
725
791
  if es_saludo or es_consulta or es_caso:
726
- logging.info("Sin ambiguedad")
792
+ logging.info("Respuesta Clara")
727
793
  self.notify("discriminando...")
728
794
  if es_saludo:
729
795
  dicriminador = "saluda"
@@ -732,12 +798,14 @@ class Dialog(ABC):
732
798
  elif es_caso:
733
799
  dicriminador = "caso"
734
800
  else:
735
- logging.info("Hay ambiguedad")
801
+ logging.info("Respuesta con ambiguedad")
736
802
  self.notify("identificando ambiguedad...")
737
- if saludo == "SALUDO":
738
- dicriminador = "saluda"
739
- else:
803
+ if caso == "QUEJA_DEMANDA":
804
+ dicriminador = "caso"
805
+ elif consulta == "PREGUNTA_O_SOLICITUD":
740
806
  dicriminador = "consulta"
807
+ elif saludo == "SALUDO":
808
+ dicriminador = "saluda"
741
809
  #--------------------------
742
810
  # Obtiene los hijos del
743
811
  # nodo
@@ -880,7 +948,8 @@ class Dialog(ABC):
880
948
  #---------------------------
881
949
  # Efectua inferencia
882
950
  new_owner, new_dialog_state, res, team = self.do_transition(owner, node, query)
883
- res = self.get_text(res)
951
+ if res and not res == "ERROR" and isinstance(res, str):
952
+ res = self.get_text(res)
884
953
  return new_owner, new_dialog_state, res, team
885
954
  else:
886
955
  logging.info(f"------------RESET---------------")
@@ -909,19 +978,32 @@ class Dialog(ABC):
909
978
  if node.tool and not node.tool == "Ninguno":
910
979
  self.notify("aplicando herramienta...")
911
980
  logging.info(f"-> node tool: {node.tool}")
912
- self.__work_memory.append({"role": "user", "content": node.text})
913
- logging.info("-----")
914
- logging.info("\n%s", json.dumps(self.__work_memory, indent=4))
915
- logging.info("-----")
916
- res = self.__ai_service.generate(self.__work_memory)
917
- logging.info(f"-> node tool: {res}")
918
- res = self.get_text(res)
981
+
982
+ res = query
983
+ if "consulta" in node.text.lower():
984
+ logging.info(f"-> node team -> consulta: {query}")
985
+ else:
986
+ #self.__work_memory.append({"role": "user", "content": node.text})
987
+ logging.info("-----")
988
+ logging.info("\n%s", json.dumps(self.__work_memory, indent=4))
989
+ logging.info("-----")
990
+ res = self.__ai_service.generate(self.__work_memory)
991
+ logging.info(f"-> node tool: {res}")
992
+ res = self.get_text(res)
919
993
  # Check if res is empty
920
994
  if not res or res == "":
921
995
  self.notify("no pude hacer uso de la herramienta")
922
996
  return self.recovery(query)
923
997
  logging.info(f"-> node tool: envia -> {res}")
924
- res = self.team_inquiry(node.team, res, node.tool, False)
998
+ res = self.team_inquiry(node.team, res, node.tool, False)
999
+
1000
+ if res and not res == "ERROR" and not isinstance(res, str):
1001
+ logging.info(f"COMANDO -> node tool: recibe -> {res}")
1002
+ self.reset()
1003
+ self.notify("STOP")
1004
+ return "Web", DialogState.START, res, "Web"
1005
+
1006
+
925
1007
  else:
926
1008
  self.notify("realizando llamada...")
927
1009
  #------------------------------
@@ -1055,6 +1137,9 @@ class Dialog(ABC):
1055
1137
  if isinstance(data, str):
1056
1138
  text = data
1057
1139
  elif isinstance(data, dict):
1140
+ if 'command' in data:
1141
+ logging.info(f"Es un comando.")
1142
+ return data
1058
1143
  text = data['dto']['text'] if data and 'dto' in data and data['dto']['text'] is not None else ''
1059
1144
  else:
1060
1145
  raise ValueError("Respuesta mal formada")
@@ -34,12 +34,17 @@ operate in an agile and effective manner.
34
34
  # --------------------------------------------------------
35
35
 
36
36
  import logging
37
+ import traceback
38
+ import pandas as pd
37
39
  from abc import abstractmethod
38
40
  from .worker import Task, Worker
39
41
  from ..kernel.agent import Queue
40
42
  from ..kernel.agent import Agent
41
43
  from ..kernel.agent import Action
42
44
  from ..kernel.util import generate_short_uuid
45
+ from ..cognitive import Dialog, AugmentedGeneration
46
+ from sklearn.metrics.pairwise import cosine_similarity
47
+ from sklearn.feature_extraction.text import CountVectorizer
43
48
 
44
49
  # ----------------------------------------------------------
45
50
  # Defines system component exceptions
@@ -53,6 +58,178 @@ class DispatcherException(Exception):
53
58
  # Define Delegate Action
54
59
  # --------------------------------------------------------
55
60
 
61
+ class AgentDto():
62
+ """ Data Transfer Object """
63
+ def __init__(self, agent_id:str) -> None:
64
+ """ Constructor
65
+ @param agent_id: Agent ID
66
+ """
67
+ self.id = agent_id
68
+
69
+ class SelectedDispatcher(Action):
70
+ """ An action is a response to the occurrence of an event """
71
+
72
+ def __init__(self) -> None:
73
+ """ Constructor """
74
+ super().__init__()
75
+ self.__rewier = {}
76
+ self.__planilla = {}
77
+
78
+ def active_timeout(self, ag, time: int) -> None:
79
+ """ Active timeout
80
+ @param time: Time
81
+ """
82
+ logging.info(f"[Delegate] Send event timeout {time}")
83
+ self.adm.send_event(ag, 'timeout', {'time': time, 'command': 'start'})
84
+
85
+ def calculate_close(self, description, data: any) -> bool:
86
+ """ Check close
87
+ @param data: Data
88
+ @return: True if the agent is closed, False otherwise
89
+ """
90
+ text1 = description
91
+ text2 = data['dto']['text'] if data and 'dto' in data and data['dto']['text'] is not None else ''
92
+ logging.info(f"Text1: {text1}")
93
+ logging.info(f"Query: {text2}")
94
+ documents = [text1, text2]
95
+ count_vectorizer = CountVectorizer()
96
+ sparse_matrix = count_vectorizer.fit_transform(documents)
97
+ doc_term_matrix = sparse_matrix.todense()
98
+ df = pd.DataFrame(
99
+ doc_term_matrix,
100
+ columns=count_vectorizer.get_feature_names_out(),
101
+ index=[text1, text2],
102
+ )
103
+ res = cosine_similarity(df, df)
104
+ similarity = res[0][1]
105
+ return similarity
106
+
107
+ @abstractmethod
108
+ def manual_selection(self, data: any) -> object:
109
+ """ Manual selection
110
+ @param data: Data
111
+ @return: Tuple with the agent and the score
112
+ """
113
+ raise NotImplementedError("The method manual_selection must be implemented in the subclass")
114
+
115
+ def execute(self, data: any) -> None:
116
+ """
117
+ Response.
118
+ @param data Event data
119
+ """
120
+ try:
121
+ logging.info('Assign to agent...')
122
+ session_id = data['dto']['session']['session_id'] if 'session' in data['dto'] else None
123
+ agent_list = self.agent.get_agent_list()
124
+ agent_count = len(agent_list)
125
+ logging.debug('List of agents: ' + str(agent_list))
126
+ if session_id in self.__planilla:
127
+ mayor_ag_id = self.__planilla[session_id]
128
+ logging.info('The session is already assigned')
129
+ logging.info(f'The agent {mayor_ag_id} will be assigned')
130
+ exit = False
131
+ while not exit:
132
+ ag = self.agent.get_free_queue().get()
133
+ agent_obj = self.adm.get_agent(ag)
134
+ # Get the role
135
+ if mayor_ag_id == agent_obj.id:
136
+ logging.info(f'The agent {ag} is assigned')
137
+ self.agent.get_request_dict()[ag] = {
138
+ 'gateway': data['gateway'],
139
+ 'dtoList': []
140
+ }
141
+ self.adm.send_event(ag, 'task', data['dto'])
142
+ self.__rewier[ag] = 0
143
+ exit = True
144
+ else:
145
+ logging.debug('The agent does not match the role')
146
+ self.adm.send_event(agent_obj.get_controller(), 'notify', ag)
147
+ if ag in self.__rewier:
148
+ self.__rewier[ag] = self.__rewier[ag] + 1
149
+ else:
150
+ self.__rewier[ag] = 0
151
+ if self.__rewier[ag] >= agent_count * 3:
152
+ data['gateway'].put('ERROR')
153
+ logging.error('[Error, toAssign]: The agent is not available')
154
+ else:
155
+ score_mayor = 0
156
+ mayor_ag = self.manual_selection(data['dto'])
157
+ if mayor_ag:
158
+ score_mayor = 7
159
+ else:
160
+ # Get the agent asocciated with the data.
161
+ for agent_id in agent_list:
162
+ agent = self.adm.get_agent(agent_id)
163
+ # Chec if the agent is instance of AugmentedGeneration
164
+ if isinstance(agent, Dialog) or isinstance(agent, AugmentedGeneration):
165
+ # Get the role
166
+ role = agent.get_role()
167
+ score = self.calculate_close(role.description, data)
168
+ logging.info(f"Score: {score}")
169
+ if score > score_mayor:
170
+ score_mayor = score
171
+ mayor_ag = agent
172
+ else:
173
+ logging.info(f"The {agent_id} is not instance of AugmentedGeneration or Dialog")
174
+ # Check if the mayor agent is the same as the agent
175
+ if score_mayor > 0.501:
176
+ logging.info(f'The agent {mayor_ag.id} will be assigned')
177
+ exit = False
178
+ while not exit:
179
+ ag = self.agent.get_free_queue().get()
180
+ agent_obj = self.adm.get_agent(ag)
181
+ # Chec if the agent is instance of AugmentedGeneration
182
+ if isinstance(agent_obj, Dialog) or isinstance(agent_obj, AugmentedGeneration):
183
+ # Get the role
184
+ if mayor_ag.id == agent_obj.id:
185
+ logging.info(f'The agent {ag} is assigned')
186
+ self.agent.get_request_dict()[ag] = {
187
+ 'gateway': data['gateway'],
188
+ 'dtoList': []
189
+ }
190
+ self.adm.send_event(ag, 'task', data['dto'])
191
+ self.__rewier[ag] = 0
192
+ exit = True
193
+ self.__planilla[session_id] = mayor_ag.id
194
+ else:
195
+ logging.debug('The agent does not match the role')
196
+ self.adm.send_event(agent_obj.get_controller(), 'notify', ag)
197
+ if ag in self.__rewier:
198
+ self.__rewier[ag] = self.__rewier[ag] + 1
199
+ else:
200
+ self.__rewier[ag] = 0
201
+ if self.__rewier[ag] >= agent_count * 3:
202
+ data['gateway'].put('ERROR')
203
+ logging.error('[Error, toAssign]: The agent is not available')
204
+ else:
205
+ self.agent.get_request_dict()[ag] = {
206
+ 'gateway': data['gateway'],
207
+ 'dtoList': []
208
+ }
209
+ self.adm.send_event(ag, 'task', data['dto'])
210
+ exit = True
211
+ else:
212
+ ag = self.agent.get_free_queue().get()
213
+ self.agent.get_request_dict()[ag] = {
214
+ 'gateway': data['gateway'],
215
+ 'dtoList': []
216
+ }
217
+ self.adm.send_event(ag, 'task', data['dto'])
218
+ # Check timeout
219
+ if 'timeout' in self.agent.state:
220
+ self.active_timeout(ag, self.agent.state['timeout'])
221
+ else:
222
+ data['gateway'].put('ERROR')
223
+ logging.error('[Delegate]: Timeout not defined in the state as "timeout" key')
224
+ except Exception as e:
225
+ traceback.print_exc()
226
+ logging.error(f"[Delegate][{self.agent.id}]: {str(e)}")
227
+ data['gateway'].put('ERROR')
228
+
229
+ # --------------------------------------------------------
230
+ # Define Delegate Action by default
231
+ # --------------------------------------------------------
232
+
56
233
  class Delegate(Action):
57
234
  """ An action is a response to the occurrence of an event """
58
235
 
@@ -0,0 +1,13 @@
1
+ Metadata-Version: 2.2
2
+ Name: pbesa
3
+ Version: 4.0.11
4
+ License-File: LICENSE
5
+ License-File: LICENSE.txt
6
+ Requires-Dist: pymongo>=4.6.3
7
+ Requires-Dist: requests>=2.32.3
8
+ Requires-Dist: azure-ai-projects>=1.0.0b6
9
+ Requires-Dist: azure-ai-inference>=1.0.0b9
10
+ Requires-Dist: azure-identity>=1.21.0
11
+ Requires-Dist: pandas>=2.2.3
12
+ Requires-Dist: scikit-learn>=1.6.1
13
+ Dynamic: requires-dist
@@ -73,6 +73,8 @@ pbesa.egg-info/top_level.txt
73
73
  pbesa/celulas/__init__.py
74
74
  pbesa/celulas/celula_casos.py
75
75
  pbesa/celulas/celula_consultas.py
76
+ pbesa/celulas/celula_datos_identificables.py
77
+ pbesa/celulas/celula_generar_documento.py
76
78
  pbesa/celulas/celula_saludos.py
77
79
  pbesa/celulas/web.py
78
80
  pbesa/kernel/__init__.py
@@ -0,0 +1,7 @@
1
+ pymongo>=4.6.3
2
+ requests>=2.32.3
3
+ azure-ai-projects>=1.0.0b6
4
+ azure-ai-inference>=1.0.0b9
5
+ azure-identity>=1.21.0
6
+ pandas>=2.2.3
7
+ scikit-learn>=1.6.1
pbesa-4.0.11/setup.py ADDED
@@ -0,0 +1,18 @@
1
+ from setuptools import setup, find_packages
2
+
3
+
4
+
5
+ setup(
6
+ name='pbesa',
7
+ version='4.0.11',
8
+ packages=find_packages(),
9
+ install_requires=[
10
+ 'pymongo>=4.6.3',
11
+ 'requests>=2.32.3',
12
+ 'azure-ai-projects>=1.0.0b6',
13
+ 'azure-ai-inference>=1.0.0b9',
14
+ 'azure-identity>=1.21.0',
15
+ 'pandas>=2.2.3',
16
+ 'scikit-learn>=1.6.1',
17
+ ],
18
+ )
pbesa-4.0.9/PKG-INFO DELETED
@@ -1,11 +0,0 @@
1
- Metadata-Version: 2.2
2
- Name: pbesa
3
- Version: 4.0.9
4
- License-File: LICENSE
5
- License-File: LICENSE.txt
6
- Requires-Dist: pymongo==4.6.3
7
- Requires-Dist: requests==2.32.3
8
- Requires-Dist: azure-ai-projects==1.0.0b6
9
- Requires-Dist: azure-ai-inference==1.0.0b9
10
- Requires-Dist: azure-identity==1.20.0
11
- Dynamic: requires-dist
@@ -1,11 +0,0 @@
1
- Metadata-Version: 2.2
2
- Name: pbesa
3
- Version: 4.0.9
4
- License-File: LICENSE
5
- License-File: LICENSE.txt
6
- Requires-Dist: pymongo==4.6.3
7
- Requires-Dist: requests==2.32.3
8
- Requires-Dist: azure-ai-projects==1.0.0b6
9
- Requires-Dist: azure-ai-inference==1.0.0b9
10
- Requires-Dist: azure-identity==1.20.0
11
- Dynamic: requires-dist
@@ -1,5 +0,0 @@
1
- pymongo==4.6.3
2
- requests==2.32.3
3
- azure-ai-projects==1.0.0b6
4
- azure-ai-inference==1.0.0b9
5
- azure-identity==1.20.0
pbesa-4.0.9/setup.py DELETED
@@ -1,16 +0,0 @@
1
- from setuptools import setup, find_packages
2
-
3
-
4
-
5
- setup(
6
- name='pbesa',
7
- version='4.0.9',
8
- packages=find_packages(),
9
- install_requires=[
10
- 'pymongo==4.6.3',
11
- 'requests==2.32.3',
12
- 'azure-ai-projects==1.0.0b6',
13
- 'azure-ai-inference==1.0.0b9',
14
- 'azure-identity==1.20.0'
15
- ],
16
- )
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes