pbesa 4.0.6__tar.gz → 4.0.8__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.6 → pbesa-4.0.8}/PKG-INFO +1 -1
  2. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/cognitive.py +240 -31
  3. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/kernel/res/__pycache__/__init__.cpython-39.pyc +0 -0
  4. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/kernel/util.py +0 -0
  5. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/mas.py +0 -0
  6. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/models.py +0 -0
  7. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/social/delegator.py +0 -0
  8. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/social/dialog.py +10 -2
  9. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/social/dispatcher_team.py +14 -8
  10. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/social/prompts.py +26 -0
  11. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/social/templates.py +0 -0
  12. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa.egg-info/PKG-INFO +1 -1
  13. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa.egg-info/requires.txt +0 -0
  14. {pbesa-4.0.6 → pbesa-4.0.8}/setup.py +1 -1
  15. {pbesa-4.0.6 → pbesa-4.0.8}/.gitignore +0 -0
  16. {pbesa-4.0.6 → pbesa-4.0.8}/LICENSE +0 -0
  17. {pbesa-4.0.6 → pbesa-4.0.8}/LICENSE.txt +0 -0
  18. {pbesa-4.0.6 → pbesa-4.0.8}/MANIFEST +0 -0
  19. {pbesa-4.0.6 → pbesa-4.0.8}/README.md +0 -0
  20. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/db.sqlite3 +0 -0
  21. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/helloworld/__init__.py +0 -0
  22. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/helloworld/__pycache__/__init__.cpython-36.pyc +0 -0
  23. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/helloworld/__pycache__/pbesa.cpython-36.pyc +0 -0
  24. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/helloworld/__pycache__/settings.cpython-36.pyc +0 -0
  25. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/helloworld/__pycache__/urls.cpython-36.pyc +0 -0
  26. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/helloworld/__pycache__/wsgi.cpython-36.pyc +0 -0
  27. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/helloworld/asgi.py +0 -0
  28. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/helloworld/pbesa.py +0 -0
  29. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/helloworld/settings.py +0 -0
  30. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/helloworld/urls.py +0 -0
  31. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/helloworld/wsgi.py +0 -0
  32. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/manage.py +0 -0
  33. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/translate/__init__.py +0 -0
  34. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/translate/__pycache__/__init__.cpython-36.pyc +0 -0
  35. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/translate/__pycache__/admin.cpython-36.pyc +0 -0
  36. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/translate/__pycache__/apps.cpython-36.pyc +0 -0
  37. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/translate/__pycache__/models.cpython-36.pyc +0 -0
  38. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/translate/__pycache__/urls.cpython-36.pyc +0 -0
  39. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/translate/__pycache__/views.cpython-36.pyc +0 -0
  40. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/translate/admin.py +0 -0
  41. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/translate/apps.py +0 -0
  42. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/translate/mas/controller/__pycache__/translatecontroller.cpython-36.pyc +0 -0
  43. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/translate/mas/controller/__pycache__/translatedelegate.cpython-36.pyc +0 -0
  44. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/translate/mas/controller/__pycache__/translateresponse.cpython-36.pyc +0 -0
  45. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/translate/mas/controller/translatecontroller.py +0 -0
  46. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/translate/mas/controller/translatedelegate.py +0 -0
  47. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/translate/mas/controller/translateresponse.py +0 -0
  48. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/translate/mas/worker/__pycache__/translatetask.cpython-36.pyc +0 -0
  49. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/translate/mas/worker/__pycache__/workeragent.cpython-36.pyc +0 -0
  50. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/translate/mas/worker/translatetask.py +0 -0
  51. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/translate/mas/worker/workeragent.py +0 -0
  52. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/translate/migrations/__init__.py +0 -0
  53. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/translate/migrations/__pycache__/__init__.cpython-36.pyc +0 -0
  54. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/translate/models.py +0 -0
  55. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/translate/tests.py +0 -0
  56. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/translate/urls.py +0 -0
  57. {pbesa-4.0.6 → pbesa-4.0.8}/examples/django/helloworld/translate/views.py +0 -0
  58. {pbesa-4.0.6 → pbesa-4.0.8}/examples/remote/mas/controller/__pycache__/countercontroller.cpython-36.pyc +0 -0
  59. {pbesa-4.0.6 → pbesa-4.0.8}/examples/remote/mas/controller/__pycache__/counterdelegate.cpython-36.pyc +0 -0
  60. {pbesa-4.0.6 → pbesa-4.0.8}/examples/remote/mas/controller/__pycache__/counterresponse.cpython-36.pyc +0 -0
  61. {pbesa-4.0.6 → pbesa-4.0.8}/examples/remote/mas/controller/__pycache__/translatecontroller.cpython-36.pyc +0 -0
  62. {pbesa-4.0.6 → pbesa-4.0.8}/examples/remote/mas/controller/__pycache__/translatedelegate.cpython-36.pyc +0 -0
  63. {pbesa-4.0.6 → pbesa-4.0.8}/examples/remote/mas/controller/__pycache__/translateresponse.cpython-36.pyc +0 -0
  64. {pbesa-4.0.6 → pbesa-4.0.8}/examples/remote/mas/controller/countercontroller.py +0 -0
  65. {pbesa-4.0.6 → pbesa-4.0.8}/examples/remote/mas/controller/counterdelegate.py +0 -0
  66. {pbesa-4.0.6 → pbesa-4.0.8}/examples/remote/mas/controller/counterresponse.py +0 -0
  67. {pbesa-4.0.6 → pbesa-4.0.8}/examples/remote/mas/worker/__pycache__/counteragent.cpython-36.pyc +0 -0
  68. {pbesa-4.0.6 → pbesa-4.0.8}/examples/remote/mas/worker/__pycache__/countertask.cpython-36.pyc +0 -0
  69. {pbesa-4.0.6 → pbesa-4.0.8}/examples/remote/mas/worker/__pycache__/translatetask.cpython-36.pyc +0 -0
  70. {pbesa-4.0.6 → pbesa-4.0.8}/examples/remote/mas/worker/__pycache__/workeragent.cpython-36.pyc +0 -0
  71. {pbesa-4.0.6 → pbesa-4.0.8}/examples/remote/mas/worker/counteragent.py +0 -0
  72. {pbesa-4.0.6 → pbesa-4.0.8}/examples/remote/mas/worker/countertask.py +0 -0
  73. {pbesa-4.0.6 → pbesa-4.0.8}/examples/remote/remote_a.py +0 -0
  74. {pbesa-4.0.6 → pbesa-4.0.8}/examples/remote/remote_b.py +0 -0
  75. {pbesa-4.0.6 → pbesa-4.0.8}/examples/remote/remote_c.py +0 -0
  76. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/__init__.py +0 -0
  77. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/kernel/__init__.py +0 -0
  78. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/kernel/adapter.py +0 -0
  79. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/kernel/agent.py +0 -0
  80. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/kernel/io/__init__.py +0 -0
  81. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/kernel/io/system_file.py +0 -0
  82. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/kernel/io/tcp_server.py +0 -0
  83. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/kernel/res/__init__.py +0 -0
  84. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/kernel/res/__pycache__/__init__.cpython-36.pyc +0 -0
  85. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/kernel/res/__pycache__/__init__.cpython-37.pyc +0 -0
  86. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/kernel/res/__pycache__/__init__.cpython-38.pyc +0 -0
  87. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/kernel/res/conf.json +0 -0
  88. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/kernel/world.py +0 -0
  89. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/remote/__init__.py +0 -0
  90. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/remote/adm_listener.py +0 -0
  91. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/remote/adm_listener_handler.py +0 -0
  92. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/remote/exceptions.py +0 -0
  93. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/remote/remote_adm.py +0 -0
  94. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/remote/remote_adm_handler.py +0 -0
  95. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/social/__init__.py +0 -0
  96. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/social/collaborative_team.py +0 -0
  97. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/social/delegator_team.py +0 -0
  98. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/social/selected_dispatcher_team.py +0 -0
  99. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa/social/worker.py +0 -0
  100. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa.egg-info/SOURCES.txt +0 -0
  101. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa.egg-info/dependency_links.txt +0 -0
  102. {pbesa-4.0.6 → pbesa-4.0.8}/pbesa.egg-info/top_level.txt +0 -0
  103. {pbesa-4.0.6 → pbesa-4.0.8}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pbesa
3
- Version: 4.0.6
3
+ Version: 4.0.8
4
4
  License-File: LICENSE
5
5
  License-File: LICENSE.txt
6
6
  Requires-Dist: pymongo==4.6.3
@@ -13,20 +13,25 @@
13
13
  # Define resources
14
14
  # --------------------------------------------------------
15
15
 
16
+ import uuid
16
17
  import json
17
18
  import logging
18
19
  import traceback
20
+ from .mas import Adm
19
21
  from pydantic import BaseModel
20
22
  from typing import List, Optional
21
23
  from abc import ABC, abstractmethod
22
24
  from pbesa.models import AIFoundry, AzureInference, GPTService, ServiceProvider
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, RECOVERY_PROMPT
25
+ from pbesa.social.dialog import (
26
+ DialogState, imprimir_grafo, recorrer_interacciones, extraer_diccionario_nodos,
27
+ ActionNode, DeclarativeNode, GotoNode) #, TerminalNode
28
+ from pbesa.social.prompts import CLASSIFICATION_PROMPT, DERIVE_PROMPT, RECOVERY_PROMPT, ADAPT_PROMPT
25
29
  # --------------------------------------------------------
26
30
  # Define DTOs
27
31
  # --------------------------------------------------------
28
32
 
29
33
  class InteraccionDTO(BaseModel):
34
+ id: str
30
35
  tipo: str
31
36
  texto: str
32
37
  actor: str
@@ -38,6 +43,7 @@ def interaccion_serializer(interaccion):
38
43
  if isinstance(interaccion, list):
39
44
  return [interaccion_serializer(i) for i in interaccion]
40
45
  return {
46
+ "id": interaccion["id"] if "id" in interaccion and interaccion["id"] else str(uuid.uuid4()),
41
47
  "tipo": interaccion["tipo"],
42
48
  "texto": interaccion["texto"],
43
49
  "actor": interaccion["actor"],
@@ -476,7 +482,11 @@ class Dialog(ABC):
476
482
  "counter": 0
477
483
  }
478
484
  # Define recovery message
479
- self.RECOVERY_MSG = "Lo lamento, puedes darme más detalles o reformular"
485
+ self.RECOVERY_MSG = "Lo lamento, puedes darme más detalles o reformular. O puedes recibir asistencia humana vía correo electrónico al atencion@minjsuticia.com.co o al Whatsapp 321456987."
486
+ # Define vertices list
487
+ self.__vertices = []
488
+ # Define visited nodes
489
+ self.__visited_nodes = 0
480
490
 
481
491
  def setup_world(self):
482
492
  """ Set up model method """
@@ -577,6 +587,9 @@ class Dialog(ABC):
577
587
  "performative": DialogState.START,
578
588
  "counter": 0
579
589
  }
590
+ # Reset visited nodes
591
+ self.__visited_nodes = 0
592
+ self.__vertices = []
580
593
 
581
594
  def notify(self, text):
582
595
  try:
@@ -602,6 +615,14 @@ class Dialog(ABC):
602
615
  canales = self.state['canales']
603
616
  canal = canales.get(team)
604
617
  if session_flag:
618
+ # Actualiza la sesion
619
+ session_manager = self.state['session_manager']
620
+ session_manager.update_session(self.state['session_id'], {
621
+ 'team': team,
622
+ 'owner': team,
623
+ 'performative': DialogState.START,
624
+ })
625
+ # Construye el mensaje
605
626
  dto = {
606
627
  "data": {
607
628
  'text': data,
@@ -642,9 +663,10 @@ class Dialog(ABC):
642
663
 
643
664
  def get_text(self, mensaje) -> str:
644
665
  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]: ", "")
666
+ mensaje_limpio = mensaje.replace("<|im_start|>user<|im_sep|>", "").replace("<|im_start|>system<|im_sep|>", "") \
667
+ .replace("<|im_start|>", "").replace("<|im_sep|>", "").replace("<|im_end|>", "") \
668
+ .replace("[Usuario]: ", "").replace("[Sistema]: ", "") \
669
+ .replace("<|user|>", "").replace("<|system|>", "")
648
670
  return mensaje_limpio.strip()
649
671
  else:
650
672
  return ""
@@ -680,20 +702,25 @@ class Dialog(ABC):
680
702
  }
681
703
  logging.info(f"Recovery attemps: {self.__recovery["counter"]}")
682
704
  # Verifica si se ha alcanzado el límite de recuperación
683
- if self.__recovery['counter'] <= 3:
684
- self.notify("identificando la performativa...")
705
+ if self.__recovery['counter'] <= 3 and self.__visited_nodes <= 3:
706
+ self.notify("identificando concepto...")
707
+ #--------------------------
685
708
  # Verifica que exista la performativa
686
709
  if not dialog_state in self.__dfa:
687
- self.notify("performativa no encontrada")
710
+ self.notify("concepto no encontrado")
688
711
  return self.recovery(query)
689
712
  # Performativa encontrada
690
713
  children = None
691
- self.notify("performativa encontrada")
714
+ self.notify("concepto encontrado")
715
+ #--------------------------
716
+ # Obtiene los hijos del nodo
692
717
  node = self.__dfa[dialog_state]
693
718
  if not isinstance(node, list):
694
719
  children = node.children
695
720
  else:
721
+ # Es una lista de nodos
696
722
  children = node
723
+ #--------------------------
697
724
  # Flujo de selección
698
725
  select_node = None
699
726
  self.notify("flujo de seleccion...")
@@ -724,20 +751,70 @@ class Dialog(ABC):
724
751
  logging.info(f"--> Una opción.")
725
752
  select_node = children[0]
726
753
  else:
727
- logging.info(f"???????????????????> text: {res} es terminal")
728
- # Nuevo nodo
754
+ logging.info("???> Es un nodo terminal o iniciador")
755
+ logging.warning(f"???> Es un nodo terminal o iniciador: {node.text}")
756
+ logging.warning(f"???> Es un nodo terminal o iniciador: {node.performative}")
757
+ return self.recovery(query)
758
+ #--------------------------
759
+ # Verifica si es un nodo
760
+ # que ya fue recorrido
761
+ if select_node.performative in self.__vertices:
762
+ logging.info(f"-> nodo ya recorrido: {select_node.text}")
763
+ self.__visited_nodes += 1
764
+ else:
765
+ logging.info(f"-> nodo no recorrido: {select_node.text}")
766
+ self.__visited_nodes = 0
767
+ # Maraca el nodo como visitado
768
+ self.__vertices.append(select_node.performative)
769
+ #---------------------------
770
+ # Verifica si el nodo es un
771
+ # nodo de salto
772
+ if isinstance(select_node, GotoNode):
773
+ logging.info(f"-> node de salto: {select_node.text}")
774
+ performative = select_node.text.replace("Salta a:", "").strip()
775
+ select_node = self.__dfa[performative]
776
+ logging.info(f"-> Salto: {select_node.text}, performativa: {select_node.performative}")
777
+ #---------------------------
778
+ # Efectua transicion
729
779
  if select_node:
730
780
  res = select_node.text
731
- node = select_node.children[0]
732
- # Nodo seleccionado
781
+ if select_node.children and len(select_node.children) > 0:
782
+ res = select_node.children[0].text
783
+ node = select_node.children[0]
784
+ else:
785
+ logging.info(f"-> El nodo de transición es terminal: {select_node.text}")
786
+ res = select_node.text
787
+ node = select_node
788
+ else:
789
+ logging.info(f"-> !!!!!!!!!!!!!! Concepto no encontrado !!!!!!!!!!!!!!")
790
+ if isinstance(node, list) and len(node) > 0:
791
+ node = node[0]
792
+ else:
793
+ logging.info(f"-> !!!!!!!!!!!!!! Concepto no encontrado ????????????????")
794
+ return self.recovery(query)
733
795
  logging.info(f"Flujo normal: {res}")
734
796
  self.notify(res)
797
+ #---------------------------
798
+ # Verifica si el nuevo nodo
799
+ # es un nodo de salto
800
+ if isinstance(node, GotoNode):
801
+ logging.info(f"-> node de salto: {node.text}")
802
+ performative = node.text.replace("Salta a:", "").strip()
803
+ node = self.__dfa[performative]
804
+ logging.info(f"-> Salto: {node.text}, performativa: {node.performative}")
805
+ #---------------------------
806
+ # Actualiza la memoria de
807
+ # trabajo
735
808
  if team_source:
736
809
  self.__work_memory.append({"role": "user", "content": res})
810
+ logging.info(f"-> Actualiza WM: {res}")
737
811
  else:
738
812
  self.__work_memory.append({"role": "user", "content": query})
739
- self.__work_memory.append({"role": "user", "content": res})
740
- # Efectua inferencia
813
+ #self.__work_memory.append({"role": "user", "content": res})
814
+ logging.info(f"-> Actualiza q-WM: {query}")
815
+ #logging.info(f"-> Actualiza r-WM: {res}")
816
+ #---------------------------
817
+ # Efectua inferencia
741
818
  new_owner, new_dialog_state, res, team = self.do_transition(owner, node, query)
742
819
  res = self.get_text(res)
743
820
  return new_owner, new_dialog_state, res, team
@@ -792,16 +869,22 @@ class Dialog(ABC):
792
869
  if node.is_terminal:
793
870
  logging.info(f"-> node team -> es terminal -> {node.text}")
794
871
  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)
872
+
873
+ res = query
874
+ if "consulta" in node.text.lower():
875
+ logging.info(f"-> node team -> consulta: {query}")
876
+ else:
877
+ logging.info("-----")
878
+ logging.info("\n%s", json.dumps(self.__work_memory, indent=4))
879
+ logging.info("-----")
880
+ res = self.__ai_service.generate(self.__work_memory)
881
+ res = self.get_text(res)
882
+ self.__work_memory.append({"role": "system", "content": res})
883
+ # Check if res is empty
884
+ if not res or res == "":
885
+ self.notify(f"no pude contactar al agente: {node.team}")
886
+ return self.recovery(query)
887
+
805
888
  self.notify(f"le envio al agente {node.team}: {res}")
806
889
  logging.info(f"-> node team -> envia: {res}")
807
890
  res = self.team_inquiry(node.team, res, None, True)
@@ -813,11 +896,27 @@ class Dialog(ABC):
813
896
  else:
814
897
  return self.recovery(query)
815
898
  else:
899
+
816
900
  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)
901
+ self.__work_memory.append({"role": "user", "content": node.text})
902
+ res = query
903
+ if "consulta" in node.text.lower():
904
+ logging.info(f"-> node team -> consulta: {query}")
905
+ else:
906
+ logging.info(f"-> node team -> sentencia: {node.text}")
907
+ logging.info("-----")
908
+ logging.info("\n%s", json.dumps(self.__work_memory, indent=4))
909
+ logging.info("-----")
910
+ res = self.get_text(res)
911
+ self.__work_memory.append({"role": "system", "content": res})
912
+ # Check if res is empty
913
+ if not res or res == "":
914
+ self.notify(f"no pude contactar al agente: {node.team}")
915
+ return self.recovery(query)
916
+ self.notify(f"le envio al agente {node.team}: {res}")
917
+ res = self.team_inquiry(node.team, res, node.tool, False)
820
918
  self.notify(f"continuando con díalogo")
919
+
821
920
  # Adiciona el texto al work memory
822
921
  if res and not res == "ERROR" and not res == "":
823
922
  logging.info(f"-> Adicion WM node team -> text: {res}")
@@ -861,8 +960,10 @@ class Dialog(ABC):
861
960
  self.notify(f"finalizando díalogo de inferencia")
862
961
  logging.info(f"Tipe node: {type(node)}")
863
962
  logging.info(f"$$$> new_owner: {owner} new_dialog_state: {new_dialog_state}")
963
+ #logging.info(f"------------RESET---------------")
964
+ #self.reset()
864
965
  self.notify("STOP")
865
- return owner, new_dialog_state, res, owner
966
+ return "Web", DialogState.START, res, "Web"
866
967
  logging.info("END: do_transition")
867
968
  except Exception as e:
868
969
  traceback.print_exc()
@@ -876,4 +977,112 @@ class Dialog(ABC):
876
977
  :param query: query
877
978
  :return: str
878
979
  """
879
- self.knowledge = knowledge
980
+ self.knowledge = knowledge
981
+
982
+ def adapt(self, data, profile) -> any:
983
+ """ Adapt method
984
+ :param data: data
985
+ :return: str
986
+ """
987
+ try:
988
+ logging.info(f"Adaptando respuesta: {data}")
989
+ # Get text
990
+ text = ""
991
+ if isinstance(data, str):
992
+ text = data
993
+ elif isinstance(data, dict):
994
+ text = data['dto']['text'] if data and 'dto' in data and data['dto']['text'] is not None else ''
995
+ else:
996
+ raise ValueError("Respuesta mal formada")
997
+ # Adapt the data
998
+ tmp_work_memory = []
999
+ prompt = ADAPT_PROMPT % (text, profile)
1000
+ tmp_work_memory.append({"role": "user", "content": prompt})
1001
+ res = self.__ai_service.generate(tmp_work_memory)
1002
+ res = self.get_text(res)
1003
+ logging.info(f"Respuesta adaptada: {res}")
1004
+ if not res or res == "":
1005
+ res = text
1006
+ logging.warning(f"No se pudo adaptar la respuesta.")
1007
+ return res
1008
+ except Exception as e:
1009
+ logging.error(f"Error al adaptar el dato: {data}")
1010
+ logging.error(e)
1011
+ return None
1012
+
1013
+ # --------------------------------------------------------
1014
+ # Define Special Dispatch
1015
+ # --------------------------------------------------------
1016
+
1017
+ class SpecialDispatch():
1018
+ """ Special dispatch """
1019
+
1020
+ def __init__(self) -> None:
1021
+ """ Constructor method """
1022
+ self.model:any = None
1023
+ self.model_conf:dict = None
1024
+ self.__meta_work_memory:list = []
1025
+ # Define AI service
1026
+ self.__ai_service = None
1027
+ self.knowledge = None
1028
+ # Define options dictionary
1029
+ self.__options_dict = {}
1030
+ # Reference of ADM
1031
+ self.adm = Adm()
1032
+
1033
+ def load_model(self, provider, config, ai_service=None) -> None:
1034
+ self.__service_provider, service = define_service_provider(provider, ai_service)
1035
+ service.setup(config)
1036
+ self.__ai_service = service
1037
+ # Setup options dictionary
1038
+ agent_list = self.get_agent_list()
1039
+ # Get the agent asocciated with the data.
1040
+ for agent_id in agent_list:
1041
+ agent = self.adm.get_agent(agent_id)
1042
+ # Check if the agent is instance of Dialog
1043
+ if isinstance(agent, Dialog):
1044
+ # Get the role
1045
+ role = agent.get_role()
1046
+ self.__options_dict[agent_id] = role.description
1047
+
1048
+ def get_text(self, mensaje) -> str:
1049
+ if mensaje:
1050
+ mensaje_limpio = mensaje.replace("<|im_start|>user<|im_sep|>", "").replace("<|im_start|>system<|im_sep|>", "") \
1051
+ .replace("<|im_start|>", "").replace("<|im_sep|>", "").replace("<|im_end|>", "") \
1052
+ .replace("[Usuario]: ", "").replace("[Sistema]: ", "") \
1053
+ .replace("<|user|>", "").replace("<|system|>", "")
1054
+ return mensaje_limpio.strip()
1055
+ else:
1056
+ return ""
1057
+
1058
+ def special_dispatch(self, data: any) -> None:
1059
+ """
1060
+ Response.
1061
+ @param data Event data
1062
+ """
1063
+ logging.info("Despachando por descripcion...")
1064
+ options = ""
1065
+ cont = 1
1066
+ agent_options = {}
1067
+ for agent, item in self.__options_dict.items():
1068
+ agent_options[cont] = agent
1069
+ options += f"{cont}) {item}\n"
1070
+ cont += 1
1071
+ query = data['dto']['text'] if data and 'dto' in data and data['dto']['text'] is not None else ''
1072
+ prompt = CLASSIFICATION_PROMPT % (query, options)
1073
+ logging.info(f"Query: {query},\n Options:\n{options}")
1074
+ self.__meta_work_memory.append({"role": "user", "content": prompt})
1075
+ res = self.__ai_service.generate(self.__meta_work_memory)
1076
+ logging.info(f"Thought: {res}")
1077
+ self.__meta_work_memory = []
1078
+ res = self.get_text(res)
1079
+ select_agent = None
1080
+ for option in range(1, cont+1):
1081
+ if str(option) in res:
1082
+ select_agent = agent_options[option]
1083
+ logging.info(f"Descripcion del agente seleccionado: {select_agent}")
1084
+ break
1085
+ if not select_agent:
1086
+ logging.info("=> No se seleccionó ningun agente")
1087
+ return select_agent
1088
+
File without changes
File without changes
File without changes
File without changes
@@ -37,7 +37,7 @@ class DialogState:
37
37
  class Node:
38
38
  def __init__(self, actor, performative, text=None, is_terminal=False):
39
39
  self.actor = actor
40
- self.performative = performative # Se asigna el ID del objeto (en str)
40
+ self.performative = performative
41
41
  self.text = text
42
42
  self.is_terminal = is_terminal
43
43
  self.children = []
@@ -57,6 +57,10 @@ class ResponseNode(Node):
57
57
  def __init__(self, actor, performative, text, is_terminal=False):
58
58
  super().__init__(actor, performative=performative, text=text, is_terminal=is_terminal)
59
59
 
60
+ class GotoNode(Node):
61
+ def __init__(self, actor, performative, text, is_terminal=False):
62
+ super().__init__(actor, performative=performative, text=text, is_terminal=is_terminal)
63
+
60
64
  #------------------------------------------
61
65
  # Define functions
62
66
  #------------------------------------------
@@ -125,7 +129,7 @@ def recorrer_interacciones(obj):
125
129
  # Si tiene la clave "tipo", creamos un nodo (según su valor) y procesamos sus hijos
126
130
  if "tipo" in obj:
127
131
  # Se usa el id del diccionario convertido a cadena para 'performative'
128
- current_id = str(id(obj))
132
+ current_id = obj["id"] if "id" in obj else str(id(obj))
129
133
  texto = obj.get("texto")
130
134
 
131
135
  # Procesamos los nodos hijos buscando en las claves "interacciones" y "Interacciones"
@@ -150,6 +154,8 @@ def recorrer_interacciones(obj):
150
154
  nuevo_nodo = ActionNode(actor=obj["actor"], performative=current_id, text=texto, action=tipo, team=obj["equipo"], tool=obj["herramienta"], is_terminal=is_terminal)
151
155
  elif tipo == "respuesta de equipo":
152
156
  nuevo_nodo = ResponseNode(actor=obj["actor"], performative=current_id, text=texto, is_terminal=is_terminal)
157
+ elif tipo == "salta a":
158
+ nuevo_nodo = GotoNode(actor=obj["actor"], performative=current_id, text=texto, is_terminal=is_terminal)
153
159
  else:
154
160
  nuevo_nodo = Node(actor=obj["actor"], performative=current_id, text=texto, is_terminal=is_terminal)
155
161
 
@@ -168,8 +174,10 @@ def recorrer_interacciones(obj):
168
174
  nodos.extend(resultado)
169
175
  else:
170
176
  nodos.append(resultado)
177
+ # Devolvemos la lista de nodos encontrados
171
178
  return nodos if nodos else None
172
179
  else:
180
+ # Si no es ni lista ni diccionario, devolvemos None
173
181
  return None
174
182
  except Exception as e:
175
183
  print(f"Error al recorrer interacciones: {e}")
@@ -113,15 +113,21 @@ class ResponseAction(Action):
113
113
  """ Execute
114
114
  @param data: Data
115
115
  """
116
- request = self.agent.get_request_dict()[data['source']]
117
- if 'timeout' in data:
118
- logging.info(f"[ResponseAction][{self.agent.id}]: Timeout ******************")
119
- request['gateway'].put("TIMEOUT")
116
+ logging.info(f"[ResponseAction][{self.agent.id}]: Response: {data}")
117
+ if data['source'] in self.agent.get_request_dict():
118
+ request = self.agent.get_request_dict()[data['source']]
119
+
120
+ if 'timeout' in data:
121
+ logging.info(f"[ResponseAction][{self.agent.id}]: Timeout ******************")
122
+ request['gateway'].put("TIMEOUT")
123
+ else:
124
+ request['dtoList'].append(data['result'])
125
+ if len(request['dtoList']) >= self.agent.get_buffer_size():
126
+ self.send_response(request)
127
+ self.adm.send_event(data['source'], 'timeout', {'command': 'stop'})
120
128
  else:
121
- request['dtoList'].append(data['result'])
122
- if len(request['dtoList']) >= self.agent.get_buffer_size():
123
- self.send_response(request)
124
- self.adm.send_event(data['source'], 'timeout', {'command': 'stop'})
129
+ logging.warning(f"[ResponseAction][{self.agent.id}]: Warning ******************")
130
+ logging.warning(f"[ResponseAction][{self.agent.id}]: {data}")
125
131
 
126
132
  # --------------------------------------------------------
127
133
  # Define component
@@ -60,5 +60,31 @@ Ahora, evalúa el siguiente caso:
60
60
 
61
61
  Texto: "%s"
62
62
 
63
+ Respuesta:
64
+ """
65
+
66
+ ADAPT_PROMPT = """
67
+ Instrucciones:
68
+
69
+ Eres un un asistente experto en comunicación. Recibirás un texto original y un perfil de adaptación. Tu tarea es reescribir el texto para que se alinee completamente con el estilo, tono y objetivo comunicativo del perfil.
70
+
71
+ Requisitos:
72
+
73
+ - No incluyas explicaciones, razonamientos ni texto adicional.
74
+
75
+ Ejemplo:
76
+
77
+ Texto: "Para solicitar el certificado, debe ingresar al sitio web, crear una cuenta, llenar el formulario y esperar el correo de confirmación."
78
+
79
+ Perfil de adaptación: "Usaurio Autonomo - Proporcionar respuestas directas y concisas para realizar trámites rápidamente."
80
+
81
+ Respuesta: Ingrese al sitio, cree su cuenta, complete el formulario y revise su correo.
82
+
83
+ Ahora, evalúa el siguiente caso:
84
+
85
+ Texto: "%s"
86
+
87
+ Perfil de adaptación: "%s"
88
+
63
89
  Respuesta:
64
90
  """
File without changes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pbesa
3
- Version: 4.0.6
3
+ Version: 4.0.8
4
4
  License-File: LICENSE
5
5
  License-File: LICENSE.txt
6
6
  Requires-Dist: pymongo==4.6.3
File without changes
@@ -4,7 +4,7 @@ from setuptools import setup, find_packages
4
4
 
5
5
  setup(
6
6
  name='pbesa',
7
- version='4.0.6',
7
+ version='4.0.8',
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