pbesa 4.0.4__tar.gz → 4.0.6__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 (103) hide show
  1. {pbesa-4.0.4 → pbesa-4.0.6}/PKG-INFO +1 -1
  2. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/cognitive.py +288 -192
  3. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/social/dialog.py +2 -1
  4. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/social/dispatcher_team.py +16 -3
  5. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/social/prompts.py +24 -0
  6. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/social/selected_dispatcher_team.py +1 -1
  7. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/social/worker.py +3 -3
  8. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa.egg-info/PKG-INFO +1 -1
  9. {pbesa-4.0.4 → pbesa-4.0.6}/setup.py +1 -1
  10. {pbesa-4.0.4 → pbesa-4.0.6}/.gitignore +0 -0
  11. {pbesa-4.0.4 → pbesa-4.0.6}/LICENSE +0 -0
  12. {pbesa-4.0.4 → pbesa-4.0.6}/LICENSE.txt +0 -0
  13. {pbesa-4.0.4 → pbesa-4.0.6}/MANIFEST +0 -0
  14. {pbesa-4.0.4 → pbesa-4.0.6}/README.md +0 -0
  15. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/db.sqlite3 +0 -0
  16. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/helloworld/__init__.py +0 -0
  17. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/helloworld/__pycache__/__init__.cpython-36.pyc +0 -0
  18. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/helloworld/__pycache__/pbesa.cpython-36.pyc +0 -0
  19. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/helloworld/__pycache__/settings.cpython-36.pyc +0 -0
  20. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/helloworld/__pycache__/urls.cpython-36.pyc +0 -0
  21. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/helloworld/__pycache__/wsgi.cpython-36.pyc +0 -0
  22. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/helloworld/asgi.py +0 -0
  23. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/helloworld/pbesa.py +0 -0
  24. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/helloworld/settings.py +0 -0
  25. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/helloworld/urls.py +0 -0
  26. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/helloworld/wsgi.py +0 -0
  27. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/manage.py +0 -0
  28. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/translate/__init__.py +0 -0
  29. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/translate/__pycache__/__init__.cpython-36.pyc +0 -0
  30. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/translate/__pycache__/admin.cpython-36.pyc +0 -0
  31. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/translate/__pycache__/apps.cpython-36.pyc +0 -0
  32. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/translate/__pycache__/models.cpython-36.pyc +0 -0
  33. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/translate/__pycache__/urls.cpython-36.pyc +0 -0
  34. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/translate/__pycache__/views.cpython-36.pyc +0 -0
  35. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/translate/admin.py +0 -0
  36. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/translate/apps.py +0 -0
  37. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/translate/mas/controller/__pycache__/translatecontroller.cpython-36.pyc +0 -0
  38. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/translate/mas/controller/__pycache__/translatedelegate.cpython-36.pyc +0 -0
  39. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/translate/mas/controller/__pycache__/translateresponse.cpython-36.pyc +0 -0
  40. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/translate/mas/controller/translatecontroller.py +0 -0
  41. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/translate/mas/controller/translatedelegate.py +0 -0
  42. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/translate/mas/controller/translateresponse.py +0 -0
  43. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/translate/mas/worker/__pycache__/translatetask.cpython-36.pyc +0 -0
  44. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/translate/mas/worker/__pycache__/workeragent.cpython-36.pyc +0 -0
  45. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/translate/mas/worker/translatetask.py +0 -0
  46. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/translate/mas/worker/workeragent.py +0 -0
  47. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/translate/migrations/__init__.py +0 -0
  48. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/translate/migrations/__pycache__/__init__.cpython-36.pyc +0 -0
  49. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/translate/models.py +0 -0
  50. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/translate/tests.py +0 -0
  51. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/translate/urls.py +0 -0
  52. {pbesa-4.0.4 → pbesa-4.0.6}/examples/django/helloworld/translate/views.py +0 -0
  53. {pbesa-4.0.4 → pbesa-4.0.6}/examples/remote/mas/controller/__pycache__/countercontroller.cpython-36.pyc +0 -0
  54. {pbesa-4.0.4 → pbesa-4.0.6}/examples/remote/mas/controller/__pycache__/counterdelegate.cpython-36.pyc +0 -0
  55. {pbesa-4.0.4 → pbesa-4.0.6}/examples/remote/mas/controller/__pycache__/counterresponse.cpython-36.pyc +0 -0
  56. {pbesa-4.0.4 → pbesa-4.0.6}/examples/remote/mas/controller/__pycache__/translatecontroller.cpython-36.pyc +0 -0
  57. {pbesa-4.0.4 → pbesa-4.0.6}/examples/remote/mas/controller/__pycache__/translatedelegate.cpython-36.pyc +0 -0
  58. {pbesa-4.0.4 → pbesa-4.0.6}/examples/remote/mas/controller/__pycache__/translateresponse.cpython-36.pyc +0 -0
  59. {pbesa-4.0.4 → pbesa-4.0.6}/examples/remote/mas/controller/countercontroller.py +0 -0
  60. {pbesa-4.0.4 → pbesa-4.0.6}/examples/remote/mas/controller/counterdelegate.py +0 -0
  61. {pbesa-4.0.4 → pbesa-4.0.6}/examples/remote/mas/controller/counterresponse.py +0 -0
  62. {pbesa-4.0.4 → pbesa-4.0.6}/examples/remote/mas/worker/__pycache__/counteragent.cpython-36.pyc +0 -0
  63. {pbesa-4.0.4 → pbesa-4.0.6}/examples/remote/mas/worker/__pycache__/countertask.cpython-36.pyc +0 -0
  64. {pbesa-4.0.4 → pbesa-4.0.6}/examples/remote/mas/worker/__pycache__/translatetask.cpython-36.pyc +0 -0
  65. {pbesa-4.0.4 → pbesa-4.0.6}/examples/remote/mas/worker/__pycache__/workeragent.cpython-36.pyc +0 -0
  66. {pbesa-4.0.4 → pbesa-4.0.6}/examples/remote/mas/worker/counteragent.py +0 -0
  67. {pbesa-4.0.4 → pbesa-4.0.6}/examples/remote/mas/worker/countertask.py +0 -0
  68. {pbesa-4.0.4 → pbesa-4.0.6}/examples/remote/remote_a.py +0 -0
  69. {pbesa-4.0.4 → pbesa-4.0.6}/examples/remote/remote_b.py +0 -0
  70. {pbesa-4.0.4 → pbesa-4.0.6}/examples/remote/remote_c.py +0 -0
  71. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/__init__.py +0 -0
  72. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/kernel/__init__.py +0 -0
  73. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/kernel/adapter.py +0 -0
  74. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/kernel/agent.py +0 -0
  75. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/kernel/io/__init__.py +0 -0
  76. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/kernel/io/system_file.py +0 -0
  77. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/kernel/io/tcp_server.py +0 -0
  78. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/kernel/res/__init__.py +0 -0
  79. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/kernel/res/__pycache__/__init__.cpython-36.pyc +0 -0
  80. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/kernel/res/__pycache__/__init__.cpython-37.pyc +0 -0
  81. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/kernel/res/__pycache__/__init__.cpython-38.pyc +0 -0
  82. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/kernel/res/__pycache__/__init__.cpython-39.pyc +0 -0
  83. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/kernel/res/conf.json +0 -0
  84. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/kernel/util.py +0 -0
  85. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/kernel/world.py +0 -0
  86. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/mas.py +0 -0
  87. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/models.py +0 -0
  88. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/remote/__init__.py +0 -0
  89. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/remote/adm_listener.py +0 -0
  90. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/remote/adm_listener_handler.py +0 -0
  91. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/remote/exceptions.py +0 -0
  92. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/remote/remote_adm.py +0 -0
  93. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/remote/remote_adm_handler.py +0 -0
  94. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/social/__init__.py +0 -0
  95. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/social/collaborative_team.py +0 -0
  96. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/social/delegator.py +0 -0
  97. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/social/delegator_team.py +0 -0
  98. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa/social/templates.py +0 -0
  99. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa.egg-info/SOURCES.txt +0 -0
  100. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa.egg-info/dependency_links.txt +0 -0
  101. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa.egg-info/requires.txt +0 -0
  102. {pbesa-4.0.4 → pbesa-4.0.6}/pbesa.egg-info/top_level.txt +0 -0
  103. {pbesa-4.0.4 → pbesa-4.0.6}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pbesa
3
- Version: 4.0.4
3
+ Version: 4.0.6
4
4
  License-File: LICENSE
5
5
  License-File: LICENSE.txt
6
6
  Requires-Dist: pymongo==4.6.3
@@ -21,7 +21,7 @@ from typing import List, Optional
21
21
  from abc import ABC, abstractmethod
22
22
  from pbesa.models import AIFoundry, AzureInference, GPTService, ServiceProvider
23
23
  from pbesa.social.dialog import DialogState, imprimir_grafo, recorrer_interacciones, extraer_diccionario_nodos, ActionNode, DeclarativeNode#, TerminalNode
24
- from pbesa.social.prompts import CLASSIFICATION_PROMPT, DERIVE_PROMPT
24
+ from pbesa.social.prompts import CLASSIFICATION_PROMPT, DERIVE_PROMPT, RECOVERY_PROMPT
25
25
  # --------------------------------------------------------
26
26
  # Define DTOs
27
27
  # --------------------------------------------------------
@@ -468,6 +468,15 @@ class Dialog(ABC):
468
468
  self.__deep_limit = 3
469
469
  # Define knowledge
470
470
  self.knowledge = None
471
+ # Define point recovery
472
+ self.__recovery = {
473
+ "owner": "Web",
474
+ "team": "Web",
475
+ "performative": DialogState.START,
476
+ "counter": 0
477
+ }
478
+ # Define recovery message
479
+ self.RECOVERY_MSG = "Lo lamento, puedes darme más detalles o reformular"
471
480
 
472
481
  def setup_world(self):
473
482
  """ Set up model method """
@@ -518,29 +527,29 @@ class Dialog(ABC):
518
527
  self.setup_world()
519
528
  interations = agent_metadata.role.interactions
520
529
  grafo = recorrer_interacciones(interations)
521
- logging.info("")
530
+ logging.debug("")
522
531
  # Si el grafo es una lista de nodos, lo imprimimos cada uno
523
532
  if isinstance(grafo, list):
524
533
  for nodo in grafo:
525
534
  imprimir_grafo(nodo)
526
535
  else:
527
536
  imprimir_grafo(grafo)
528
- logging.info("")
537
+ logging.debug("")
529
538
  # Ejemplo de uso:
530
539
  self.__dfa = extraer_diccionario_nodos(grafo)
531
540
  # Mostrar el diccionario
532
541
  for clave, valor in self.__dfa.items():
533
- logging.info(f"{clave}: {valor.text}")
534
- logging.info("")
542
+ logging.debug(f"{clave}: {valor.text}")
543
+ logging.debug("")
535
544
  iniciadores = []
536
545
  for item in interations:
537
546
  for clave, valor in self.__dfa.items():
538
547
  if valor.text == item['texto']:
539
548
  iniciadores.append(valor)
540
- logging.info("Iniciadores:")
549
+ logging.debug("Iniciadores:")
541
550
  for iniciador in iniciadores:
542
- logging.info(iniciador.text)
543
- logging.info("")
551
+ logging.debug(iniciador.text)
552
+ logging.debug("")
544
553
  # Set dialog state
545
554
  self.__dfa['start'] = iniciadores
546
555
 
@@ -561,219 +570,306 @@ class Dialog(ABC):
561
570
  self.__work_memory = []
562
571
  # Set up model
563
572
  self.setup_world()
564
-
565
- def team_inquiry(self, team, data, operation, session_flag) -> str:
566
- canales = self.state['canales']
567
- canal = canales.get(team)
568
- dto = None
569
- if operation:
573
+ # Reset dialog state
574
+ self.__recovery = {
575
+ "owner": "Web",
576
+ "team": "Web",
577
+ "performative": DialogState.START,
578
+ "counter": 0
579
+ }
580
+
581
+ def notify(self, text):
582
+ try:
583
+ canales = self.state['canales']
584
+ canal = canales.get("Webhook")
585
+ session_id = self.state['session_id']
570
586
  dto = {
571
- "data": {
572
- 'text': data,
573
- 'operation': operation
574
- },
587
+ "session_id": session_id,
588
+ "text": text[0:100]
575
589
  }
576
- else:
577
- if session_flag:
578
- logging.info(f"Session flag: {session_flag}")
579
- logging.info(f"------------RESET--------------- {data}")
580
- self.reset()
581
- return data
582
-
590
+ response = canal.post("notify", dto)
591
+ if response['status']:
592
+ logging.info(f"Notificación enviada: {text}")
583
593
  else:
594
+ logging.warning(f"Notificación no enviada: {text}")
595
+ except Exception as e:
596
+ logging.error(f"Error al enviar notificación: {text}")
597
+ logging.erro(f"Error: {e}")
598
+
599
+ def team_inquiry(self, team, data, operation, session_flag) -> str:
600
+ try:
601
+ dto = None
602
+ canales = self.state['canales']
603
+ canal = canales.get(team)
604
+ if session_flag:
584
605
  dto = {
585
606
  "data": {
586
- 'text': data
607
+ 'text': data,
608
+ 'session_id': self.state['session_id'],
587
609
  },
588
610
  }
589
- response = canal.post(team.lower(), dto)
590
- if response['status']:
591
- return response['message']['response']
592
-
593
- logging.info(f"------------RESET---------------")
594
- self.reset()
595
- return "Lo lamento, no puedo responder en este momento"
596
-
611
+ # Evia mensaje a los agentes remotos
612
+ logging.info('>>>> Call remote agent: team.\n')
613
+ response = canal.post(team.lower(), dto)
614
+ if response and not response['status']:
615
+ logging.error(f'No se pudo establecer la comunicación con el agente remoto')
616
+ return None
617
+ logging.info(f'>>>> Response: {response}')
618
+ return response['message']['response']
619
+ else:
620
+ if operation:
621
+ dto = {
622
+ "data": {
623
+ 'text': data,
624
+ 'operation': operation
625
+ },
626
+ }
627
+ else:
628
+ dto = {
629
+ "data": {
630
+ 'text': data
631
+ },
632
+ }
633
+ response = canal.post(team.lower(), dto)
634
+ if response['status']:
635
+ return response['message']['response']
636
+ else:
637
+ return None
638
+ logging.info("END: team_inquiry")
639
+ except Exception as e:
640
+ logging.error(f"Error al consultar al equipo: {team}")
641
+ return None
642
+
597
643
  def get_text(self, mensaje) -> str:
598
- mensaje_limpio = mensaje.replace("<|im_start|>user<|im_sep|>", "").replace("<|im_start|>system<|im_sep|>", "")
599
- mensaje_limpio = mensaje_limpio.replace("<|im_start|>", "").replace("<|im_sep|>", "").replace("<|im_end|>", "")
600
- mensaje_limpio = mensaje_limpio.replace("[Usuario]: ", "").replace("[Sistema]: ", "")
601
- return mensaje_limpio.strip()
644
+ if mensaje:
645
+ mensaje_limpio = mensaje.replace("<|im_start|>user<|im_sep|>", "").replace("<|im_start|>system<|im_sep|>", "")
646
+ mensaje_limpio = mensaje_limpio.replace("<|im_start|>", "").replace("<|im_sep|>", "").replace("<|im_end|>", "")
647
+ mensaje_limpio = mensaje_limpio.replace("[Usuario]: ", "").replace("[Sistema]: ", "")
648
+ return mensaje_limpio.strip()
649
+ else:
650
+ return ""
651
+
652
+ def recovery(self, query):
653
+ try:
654
+ prompt = RECOVERY_PROMPT % query
655
+ temp_work_memory = [{"role": "user", "content": prompt}]
656
+ res = self.__ai_service.generate(temp_work_memory)
657
+ res = self.get_text(res)
658
+ if res and not res == "":
659
+ return self.__recovery['owner'], self.__recovery['performative'], res, self.__recovery['team']
660
+ else:
661
+ logging.info(f"------------RESET---------------")
662
+ logging.info(f"Recovery from: {self.__recovery['performative']}")
663
+ self.reset()
664
+ self.notify("STOP")
665
+ return "Web", DialogState.START, self.RECOVERY_MSG, "Web"
666
+ except Exception as e:
667
+ return self.RECOVERY_MSG
602
668
 
603
669
  def transition(self, owner, dialog_state, query, team_source=False) -> str:
604
- logging.info(f"Transition: {owner} -> {dialog_state}, Team: {team_source}, Query: {query}")
605
- text = ""
606
-
607
- # Verifica que exista la performativa
608
- if not dialog_state in self.__dfa:
609
- logging.warning(f"------------Performativa no existe---------------")
610
- self.reset()
611
- return "Web", DialogState.START, "Lo lamento, no puedo responder en este momento", "Web"
612
-
613
- node = self.__dfa[dialog_state]
614
- if not isinstance(node, list):
615
- node = node.children
616
-
617
- # Flujo de selección
618
- if node and len(node)> 1:
619
- logging.info(f"--> Más de una opción.")
620
- options = ""
621
- cont = 1
622
- for item in node:
623
- options += f"{cont}) {item.text}\n"
624
- cont += 1
625
- prompt = CLASSIFICATION_PROMPT % (query, options)
626
- logging.info(f"Query: {query},\n Options:\n{options}")
627
- self.__meta_work_memory.append({"role": "user", "content": prompt})
628
- text = self.__ai_service.generate(self.__meta_work_memory)
629
- logging.info(f"Thought: {text}")
630
- self.__meta_work_memory = []
631
- text = self.get_text(text)
632
- select_node = None
633
- for option in range(1, cont):
634
- if str(option) in text:
635
- select_node = node[option-1]
636
- logging.info(f"Select node: {select_node.text}")
637
- break
638
- if not select_node:
639
- logging.info("=> No se seleccionó ninguna opción")
640
- logging.info(f"=> Node: {node}")
641
- logging.info(f"=> len node: {len(node)}")
642
- select_node = node[0]
643
- logging.info(f"=> Selecciona el primer nodo: {select_node.text}")
644
- elif node and len(node) == 1:
645
- logging.info(f"--> Una opción.")
646
- select_node = node[0]
647
- else:
670
+ try:
671
+ res = ""
672
+ logging.info(f"TOPTQ: {owner} - {dialog_state} - {team_source} - {query}")
673
+ # Punto de restauración
674
+ counter = (self.__recovery['counter'] + 1) if self.__recovery['performative'] == dialog_state else self.__recovery['counter']
675
+ self.__recovery = {
676
+ "owner": owner,
677
+ "team": owner,
678
+ "performative": dialog_state,
679
+ "counter": counter
680
+ }
681
+ logging.info(f"Recovery attemps: {self.__recovery["counter"]}")
682
+ # Verifica si se ha alcanzado el límite de recuperación
683
+ if self.__recovery['counter'] <= 3:
684
+ self.notify("identificando la performativa...")
685
+ # Verifica que exista la performativa
686
+ if not dialog_state in self.__dfa:
687
+ self.notify("performativa no encontrada")
688
+ return self.recovery(query)
689
+ # Performativa encontrada
690
+ children = None
691
+ self.notify("performativa encontrada")
692
+ node = self.__dfa[dialog_state]
693
+ if not isinstance(node, list):
694
+ children = node.children
695
+ else:
696
+ children = node
697
+ # Flujo de selección
698
+ select_node = None
699
+ self.notify("flujo de seleccion...")
700
+ if children and len(children)> 1:
701
+ logging.info(f"--> Más de una opción.")
702
+ options = ""
703
+ cont = 1
704
+ for item in children:
705
+ options += f"{cont}) {item.text}\n"
706
+ cont += 1
707
+ prompt = CLASSIFICATION_PROMPT % (query, options)
708
+ logging.info(f"Query: {query},\n Options:\n{options}")
709
+ self.__meta_work_memory.append({"role": "user", "content": prompt})
710
+ res = self.__ai_service.generate(self.__meta_work_memory)
711
+ logging.info(f"Thought: {res}")
712
+ self.__meta_work_memory = []
713
+ res = self.get_text(res)
714
+ for option in range(1, cont):
715
+ if str(option) in res:
716
+ select_node = children[option-1]
717
+ logging.info(f"Select node: {select_node.text}")
718
+ break
719
+ if not select_node:
720
+ logging.info("=> No se seleccionó ninguna opción")
721
+ select_node = children[0]
722
+ logging.info(f"=> Selecciona el primer nodo: {select_node.text}")
723
+ elif children and len(children) == 1:
724
+ logging.info(f"--> Una opción.")
725
+ select_node = children[0]
726
+ else:
727
+ logging.info(f"???????????????????> text: {res} es terminal")
728
+ # Nuevo nodo
729
+ if select_node:
730
+ res = select_node.text
731
+ node = select_node.children[0]
732
+ # Nodo seleccionado
733
+ logging.info(f"Flujo normal: {res}")
734
+ self.notify(res)
735
+ if team_source:
736
+ self.__work_memory.append({"role": "user", "content": res})
737
+ else:
738
+ self.__work_memory.append({"role": "user", "content": query})
739
+ self.__work_memory.append({"role": "user", "content": res})
740
+ # Efectua inferencia
741
+ new_owner, new_dialog_state, res, team = self.do_transition(owner, node, query)
742
+ res = self.get_text(res)
743
+ return new_owner, new_dialog_state, res, team
744
+ else:
745
+ logging.info(f"------------RESET---------------")
746
+ self.notify("STOP")
747
+ self.reset()
748
+ return "Web", DialogState.START, self.RECOVERY_MSG, "Web"
749
+ logging.info("END: do_transition")
750
+ except Exception as e:
751
+ traceback.print_exc()
648
752
  logging.info(f"------------RESET---------------")
649
753
  self.reset()
650
- logging.info(f"???> text: {text} es terminal")
651
- text = self.get_text(text)
652
- return owner, DialogState.START, text, owner
653
-
654
- # Flujo normal
655
- logging.info(f"Flujo normal: {select_node.text}")
656
- if team_source:
657
- self.__work_memory.append({"role": "user", "content": select_node.text})
658
- else:
659
- self.__work_memory.append({"role": "user", "content": query})
660
- self.__work_memory.append({"role": "user", "content": select_node.text})
661
- new_owner, new_dialog_state, text, team = self.do_transition(owner, select_node.children[0], query)
662
- text = self.get_text(text)
663
- return new_owner, new_dialog_state, text, team
754
+ self.notify("STOP")
755
+ return owner, DialogState.START, "Lo lamento, no puedo responder en este momento", owner
664
756
 
665
757
  def do_transition(self, owner, node, query) -> str:
666
758
  """ Generate method
667
759
  :return: str
668
- """
669
- if isinstance(node, DeclarativeNode):
670
- logging.info(f"D -> node: {node.text}")
671
- self.__work_memory.append({"role": "user", "content": node.text})
672
- elif isinstance(node, ActionNode):
673
-
674
- #------------------------------
675
- # Accion
676
- #------------------------------
677
-
678
- logging.info(f"-> node action: {node.action}")
679
- if node.tool and not node.tool == "Ninguno":
680
- logging.info(f"-> node tool: {node.tool}")
681
- self.__work_memory.append({"role": "user", "content": node.text})
682
- logging.info("-----")
683
- logging.info("\n%s", json.dumps(self.__work_memory, indent=4))
684
- logging.info("-----")
685
- res = self.__ai_service.generate(self.__work_memory)
686
- logging.info(f"-> node tool: {res}")
687
- res = self.get_text(res)
688
- # Check if res is empty
689
- if not res or res == "":
690
- logging.info("1 -> res vacio")
691
- res = "Lo lamento, no puedo responder en este momento"
692
-
693
- logging.info(f"------------RESET---------------")
694
- self.reset()
695
-
696
- return owner, DialogState.START, res, owner
697
- logging.info(f"-> node tool: envia -> {res}")
698
- text = self.team_inquiry(node.team, res, node.tool, False)
699
- else:
760
+ """
761
+ try:
762
+ if isinstance(node, ActionNode):
763
+ self.notify("realizando acción...")
700
764
  #------------------------------
701
- # Lllamada
765
+ # Accion
702
766
  #------------------------------
703
- logging.info(f"-> node team: {node.team}")
704
- # Verifica si el nodo es termianl ya que significa
705
- # que el dialogo cambia de agente
706
- if node.is_terminal:
707
- logging.info(f"-> node team -> es terminal -> {node.text}")
767
+ logging.info(f"-> node action: {node.action}")
768
+ if node.tool and not node.tool == "Ninguno":
769
+ self.notify("aplicando herramienta...")
770
+ logging.info(f"-> node tool: {node.tool}")
708
771
  self.__work_memory.append({"role": "user", "content": node.text})
709
772
  logging.info("-----")
710
773
  logging.info("\n%s", json.dumps(self.__work_memory, indent=4))
711
- logging.info("-----")
774
+ logging.info("-----")
712
775
  res = self.__ai_service.generate(self.__work_memory)
776
+ logging.info(f"-> node tool: {res}")
713
777
  res = self.get_text(res)
714
- self.__work_memory.append({"role": "system", "content": res})
715
778
  # Check if res is empty
716
779
  if not res or res == "":
717
- logging.info("2 -> res vacio")
718
- res = "Lo lamento, no puedo responder en este momento"
719
- logging.info(f"------------RESET---------------")
720
- self.reset()
721
- return owner, DialogState.START, res, owner
722
- logging.info(f"-> node team -> envia: {res}")
723
- text = self.team_inquiry(node.team, res, None, True)
724
- return node.team, DialogState.START, res, node.team
780
+ self.notify("no pude hacer uso de la herramienta")
781
+ return self.recovery(query)
782
+ logging.info(f"-> node tool: envia -> {res}")
783
+ res = self.team_inquiry(node.team, res, node.tool, False)
725
784
  else:
726
- logging.info("-> node team -> continua")
727
- self.__work_memory.append({"role": "user", "content": node.text})
728
- logging.info(f"-> node team -> envia: {query}")
729
- text = self.team_inquiry(node.team, query, node.tool, False)
730
- logging.info(f"-> node team -> text: {text}")
731
- if text:
732
- logging.info(f"-> Adicion WM node team -> text: {text}")
733
- self.__work_memory.append({"role": "system", "content": text})
734
- self.__deep_count += 1
735
- if self.__deep_count < self.__deep_limit:
736
- return self.transition(owner, node.performative, text, True)
785
+ self.notify("realizando llamada...")
786
+ #------------------------------
787
+ # Lllamada
788
+ #------------------------------
789
+ logging.info(f"-> node team: {node.team}")
790
+ # Verifica si el nodo es termianl ya que significa
791
+ # que el dialogo cambia de agente
792
+ if node.is_terminal:
793
+ logging.info(f"-> node team -> es terminal -> {node.text}")
794
+ self.__work_memory.append({"role": "user", "content": node.text})
795
+ logging.info("-----")
796
+ logging.info("\n%s", json.dumps(self.__work_memory, indent=4))
797
+ logging.info("-----")
798
+ res = self.__ai_service.generate(self.__work_memory)
799
+ res = self.get_text(res)
800
+ self.__work_memory.append({"role": "system", "content": res})
801
+ # Check if res is empty
802
+ if not res or res == "":
803
+ self.notify(f"no pude contactar al agente: {node.team}")
804
+ return self.recovery(query)
805
+ self.notify(f"le envio al agente {node.team}: {res}")
806
+ logging.info(f"-> node team -> envia: {res}")
807
+ res = self.team_inquiry(node.team, res, None, True)
808
+ if res and not res == "ERROR" and not res == "":
809
+ logging.info(f"------------RESET---------------")
810
+ self.reset()
811
+ self.notify("STOP")
812
+ return node.team, DialogState.START, res, node.team
813
+ else:
814
+ return self.recovery(query)
815
+ else:
816
+ logging.info("-> node team -> continua")
817
+ self.__work_memory.append({"role": "user", "content": node.text})
818
+ logging.info(f"-> node team -> envia: {query}")
819
+ res = self.team_inquiry(node.team, query, node.tool, False)
820
+ self.notify(f"continuando con díalogo")
821
+ # Adiciona el texto al work memory
822
+ if res and not res == "ERROR" and not res == "":
823
+ logging.info(f"-> Adicion WM node team -> text: {res}")
824
+ self.__work_memory.append({"role": "system", "content": res})
825
+ else:
826
+ return self.recovery(query)
827
+ logging.info("#########> Procesa respuesta del equipo en profundidad")
828
+ # Verifica si se alcanzó el límite de profundidad
829
+ self.__deep_count += 1
830
+ if self.__deep_count < self.__deep_limit:
831
+ self.notify("efectuando inferencia en profundidad")
832
+ return self.transition(owner, node.performative, res, True)
833
+ else:
834
+ self.notify(f"se alcanzó el límite de profundidad: {self.__deep_count}")
835
+ self.__deep_count = 0
836
+ logging.info("-> node team -> deep limit")
837
+ logging.info(f"------------RESET---------------")
838
+ self.notify("STOP")
839
+ self.reset()
840
+ return "Web", DialogState.START, self.RECOVERY_MSG, "Web"
737
841
  else:
738
- self.__deep_count = 0
739
- logging.info("-> node team -> deep limit")
740
-
741
- logging.info(f"------------RESET---------------")
742
- self.reset()
743
-
744
- return "Web", DialogState.START, "Lo lamento me he perdido, ¿podrías repetir la pregunta?"
745
- else:
746
- logging.info(f"!!!!!!!!!!!!!!!!!!!!!!!> Otro tipo de nodo: {node.text}")
747
-
748
- logging.info(f"=> !!!!: {query}")
749
- logging.info("-----")
750
- logging.info("\n%s", json.dumps(self.__work_memory, indent=4))
751
- logging.info("-----")
752
- res = self.__ai_service.generate(self.__work_memory)
753
- logging.info(f"=> res: {res}")
754
- res = self.get_text(res)
755
- self.__work_memory.append({"role": "system", "content": res})
756
- # Check if res is empty
757
- if not res or res == "":
758
- logging.info("3 -> res vacio")
759
-
842
+ self.notify("efectuando inferencia...")
843
+ logging.info(f"D -> node: {node.text}")
844
+ self.__work_memory.append({"role": "user", "content": node.text})
845
+ logging.info(f"=> !!!!: {query}")
846
+ logging.info("-----")
847
+ logging.info("\n%s", json.dumps(self.__work_memory, indent=4))
848
+ logging.info("-----")
849
+ res = self.__ai_service.generate(self.__work_memory)
850
+ res = self.get_text(res)
851
+ self.__work_memory.append({"role": "system", "content": res})
852
+ # Check if res is empty
853
+ if not res or res == "":
854
+ return self.recovery(query)
855
+ logging.info(f"=> Thought DEEP: {res}")
856
+ self.notify(f"Realizando inferencia: {res}")
857
+ new_dialog_state = node.performative
858
+ if not node.is_terminal:
859
+ self.notify(f"continuando díalogo de inferencia")
860
+ return owner, new_dialog_state, res, owner
861
+ self.notify(f"finalizando díalogo de inferencia")
862
+ logging.info(f"Tipe node: {type(node)}")
863
+ logging.info(f"$$$> new_owner: {owner} new_dialog_state: {new_dialog_state}")
864
+ self.notify("STOP")
865
+ return owner, new_dialog_state, res, owner
866
+ logging.info("END: do_transition")
867
+ except Exception as e:
868
+ traceback.print_exc()
760
869
  logging.info(f"------------RESET---------------")
761
870
  self.reset()
762
-
763
- res = "Lo lamento, no puedo responder en este momento"
764
- return owner, DialogState.START, res, owner
765
-
766
- logging.info(f"=> Thought DEEP: {res}")
767
-
768
- new_dialog_state = node.performative
769
- if not node.is_terminal:
770
- logging.info(f"=> new_owner: {owner} new_dialog_state: {new_dialog_state}")
771
- return owner, new_dialog_state, res, owner
772
-
773
- logging.info(f"Tipe node: {type(node)}")
774
-
775
- logging.info(f"$$$> new_owner: {owner} new_dialog_state: {new_dialog_state}")
776
- return owner, new_dialog_state, res, owner
871
+ self.notify("STOP")
872
+ return owner, DialogState.START, "Lo lamento, no puedo responder en este momento", owner
777
873
 
778
874
  def set_knowledge(self, knowledge) -> str:
779
875
  """ Set knowledge method
@@ -13,6 +13,7 @@
13
13
  # Define resources
14
14
  # --------------------------------------------------------
15
15
 
16
+ import logging
16
17
  import datetime
17
18
  import traceback
18
19
  from .templates import AFIRMATIVE_RESPONSE, GET_DATE
@@ -199,6 +200,6 @@ def imprimir_grafo(nodo, nivel=0):
199
200
  indent = " " * nivel
200
201
  # Se muestra la clase del nodo y algunos atributos
201
202
  clase = nodo.__class__.__name__
202
- print(f"{indent}{clase} (performative: {nodo.performative}, text/action: {nodo.text if hasattr(nodo, 'text') and nodo.text is not None else getattr(nodo, 'action', None)}, terminal: {nodo.is_terminal})")
203
+ logging.debug(f"{indent}{clase} (performative: {nodo.performative}, text/action: {nodo.text if hasattr(nodo, 'text') and nodo.text is not None else getattr(nodo, 'action', None)}, terminal: {nodo.is_terminal})")
203
204
  for child in nodo.children:
204
205
  imprimir_grafo(child, nivel + 1)
@@ -130,7 +130,7 @@ class ResponseAction(Action):
130
130
  class DispatcherController(Agent):
131
131
  """ Represents the agent that delegates the execution of actions to other agents """
132
132
 
133
- def __init__(self, agent_id:str, buffer_size:int, pool_size:int) -> None:
133
+ def __init__(self, agent_id:str, buffer_size:int, pool_size:int, delegate=None) -> None:
134
134
  """ Constructor
135
135
  @param agent_id: Agent ID
136
136
  @param type: Pool type
@@ -139,15 +139,20 @@ class DispatcherController(Agent):
139
139
  """
140
140
  self.__buffer_size = buffer_size
141
141
  self.__request_dict = {}
142
+ self.__pool_size = pool_size
142
143
  self.__free_queue = Queue(pool_size)
143
144
  self.__agent_list = []
145
+ self.__delegate = delegate
144
146
  super().__init__(agent_id)
145
147
 
146
148
  def setup(self) -> None:
147
149
  """ Set up method """
148
150
  self._social = True
149
151
  self.add_behavior('Delegate')
150
- self.bind_action('Delegate', 'delegate', Delegate())
152
+ if self.__delegate:
153
+ self.bind_action('Delegate', 'delegate', self.__delegate())
154
+ else:
155
+ self.bind_action('Delegate', 'delegate', Delegate())
151
156
  self.add_behavior('Notify')
152
157
  self.bind_action('Notify', 'notify', NotifyFreeAction())
153
158
  self.add_behavior('Response')
@@ -161,6 +166,8 @@ class DispatcherController(Agent):
161
166
  self.__agent_list.append(agent.id)
162
167
  agent.set_controller(self.id)
163
168
  agent.set_controller_type('POOL')
169
+ if len(self.__agent_list) > self.__pool_size:
170
+ raise DispatcherException('[Warn, suscribeAgent]: The pool is full')
164
171
  self.__free_queue.put(agent.id)
165
172
  actions = agent.get_actions()
166
173
  for action in actions:
@@ -181,7 +188,7 @@ class DispatcherController(Agent):
181
188
  @param event: Event
182
189
  @param data: Data
183
190
  """
184
- from pbesa.kernel.system.adm import Adm
191
+ from ..mas import Adm
185
192
  for agent_id in self.__agent_list:
186
193
  Adm().send_event(agent_id, event, data)
187
194
 
@@ -190,6 +197,12 @@ class DispatcherController(Agent):
190
197
  """ Builds the agent """
191
198
  pass
192
199
 
200
+ def get_agent_list(self) -> list:
201
+ """ Gets the agent list
202
+ @return: Agent list
203
+ """
204
+ return self.__agent_list
205
+
193
206
  def get_free_queue(self) -> Queue:
194
207
  """ Gets the free queue
195
208
  @return: Free queue
@@ -36,5 +36,29 @@ Ahora, evalúa el siguiente caso:
36
36
 
37
37
  Texto: "%s"
38
38
 
39
+ Respuesta:
40
+ """
41
+
42
+ RECOVERY_PROMPT = """
43
+ Instrucciones:
44
+
45
+ Eres un agente especializado en parafrasear. Tu tarea es analizar un texto principal y parafrasearlo generando opciones al usuario.
46
+
47
+ Requisitos:
48
+
49
+ - No incluyas explicaciones, razonamientos ni texto adicional.
50
+ - Genera opciones en lenguaje natural sin involucrar números o listas.
51
+ - Si no logras parafrasear el texto principal, responde solicitando más información.
52
+
53
+ Ejemplo:
54
+
55
+ Texto: "Hola mi caso esta relacionado con la Superfinanciera"
56
+
57
+ Respuesta: Perdona, tu solicitud ¿Es sobre la Superintendencia Financiera de Colombia o sobre la Superintendencia de Sociedades?
58
+
59
+ Ahora, evalúa el siguiente caso:
60
+
61
+ Texto: "%s"
62
+
39
63
  Respuesta:
40
64
  """
@@ -104,7 +104,7 @@ class DelegateAction(Action):
104
104
  self.__rewier[ag] = 0
105
105
  exit = True
106
106
  else:
107
- logging.info('The agent is not available')
107
+ logging.info('The agent is not operational')
108
108
  self.adm.send_event(agent_obj.get_controller(), 'notify', ag)
109
109
  if ag in self.__rewier:
110
110
  self.__rewier[ag] = self.__rewier[ag] + 1
@@ -57,18 +57,18 @@ class TimeoutAction(Action):
57
57
  """ Execute the action
58
58
  @param data: Event data
59
59
  """
60
- logging.info(f"[TimeoutAction][{self.agent.id}]: Execute {data}")
60
+ logging.debug(f"[TimeoutAction][{self.agent.id}]: Execute {data}")
61
61
  if data['command'] == 'start':
62
62
  if not self.agent.is_timeout():
63
63
  self.agent.set_timeout(True)
64
64
  self.__timer = Timer(data['time'], self.handler)
65
65
  self.__timer.start()
66
- logging.info(f"[TimeoutAction][{self.agent.id}]: Timer started")
66
+ logging.debug(f"[TimeoutAction][{self.agent.id}]: Timer started")
67
67
  else:
68
68
  if self.__timer:
69
69
  self.__timer.cancel()
70
70
  self.__timer = None
71
- logging.info(f"[TimeoutAction][{self.agent.id}]: Timer stopped")
71
+ logging.debug(f"[TimeoutAction][{self.agent.id}]: Timer stopped")
72
72
 
73
73
  # --------------------------------------------------------
74
74
  # Define Task Action
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pbesa
3
- Version: 4.0.4
3
+ Version: 4.0.6
4
4
  License-File: LICENSE
5
5
  License-File: LICENSE.txt
6
6
  Requires-Dist: pymongo==4.6.3
@@ -4,7 +4,7 @@ from setuptools import setup, find_packages
4
4
 
5
5
  setup(
6
6
  name='pbesa',
7
- version='4.0.4',
7
+ version='4.0.6',
8
8
  packages=find_packages(),
9
9
  install_requires=[
10
10
  'pymongo==4.6.3',
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
File without changes