pbesa 4.0.7__tar.gz → 4.0.9__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 (108) hide show
  1. {pbesa-4.0.7 → pbesa-4.0.9}/PKG-INFO +1 -1
  2. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/__init__.py +2 -1
  3. pbesa-4.0.9/pbesa/celulas/__init__.py +3 -0
  4. pbesa-4.0.9/pbesa/celulas/celula_casos.py +60 -0
  5. pbesa-4.0.9/pbesa/celulas/celula_consultas.py +45 -0
  6. pbesa-4.0.9/pbesa/celulas/celula_saludos.py +41 -0
  7. pbesa-4.0.9/pbesa/celulas/web.py +49 -0
  8. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/cognitive.py +294 -68
  9. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/social/dispatcher_team.py +14 -8
  10. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/social/prompts.py +26 -0
  11. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa.egg-info/PKG-INFO +1 -1
  12. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa.egg-info/SOURCES.txt +5 -0
  13. {pbesa-4.0.7 → pbesa-4.0.9}/setup.py +1 -1
  14. {pbesa-4.0.7 → pbesa-4.0.9}/.gitignore +0 -0
  15. {pbesa-4.0.7 → pbesa-4.0.9}/LICENSE +0 -0
  16. {pbesa-4.0.7 → pbesa-4.0.9}/LICENSE.txt +0 -0
  17. {pbesa-4.0.7 → pbesa-4.0.9}/MANIFEST +0 -0
  18. {pbesa-4.0.7 → pbesa-4.0.9}/README.md +0 -0
  19. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/db.sqlite3 +0 -0
  20. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/helloworld/__init__.py +0 -0
  21. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/helloworld/__pycache__/__init__.cpython-36.pyc +0 -0
  22. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/helloworld/__pycache__/pbesa.cpython-36.pyc +0 -0
  23. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/helloworld/__pycache__/settings.cpython-36.pyc +0 -0
  24. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/helloworld/__pycache__/urls.cpython-36.pyc +0 -0
  25. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/helloworld/__pycache__/wsgi.cpython-36.pyc +0 -0
  26. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/helloworld/asgi.py +0 -0
  27. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/helloworld/pbesa.py +0 -0
  28. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/helloworld/settings.py +0 -0
  29. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/helloworld/urls.py +0 -0
  30. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/helloworld/wsgi.py +0 -0
  31. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/manage.py +0 -0
  32. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/translate/__init__.py +0 -0
  33. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/translate/__pycache__/__init__.cpython-36.pyc +0 -0
  34. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/translate/__pycache__/admin.cpython-36.pyc +0 -0
  35. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/translate/__pycache__/apps.cpython-36.pyc +0 -0
  36. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/translate/__pycache__/models.cpython-36.pyc +0 -0
  37. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/translate/__pycache__/urls.cpython-36.pyc +0 -0
  38. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/translate/__pycache__/views.cpython-36.pyc +0 -0
  39. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/translate/admin.py +0 -0
  40. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/translate/apps.py +0 -0
  41. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/translate/mas/controller/__pycache__/translatecontroller.cpython-36.pyc +0 -0
  42. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/translate/mas/controller/__pycache__/translatedelegate.cpython-36.pyc +0 -0
  43. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/translate/mas/controller/__pycache__/translateresponse.cpython-36.pyc +0 -0
  44. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/translate/mas/controller/translatecontroller.py +0 -0
  45. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/translate/mas/controller/translatedelegate.py +0 -0
  46. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/translate/mas/controller/translateresponse.py +0 -0
  47. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/translate/mas/worker/__pycache__/translatetask.cpython-36.pyc +0 -0
  48. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/translate/mas/worker/__pycache__/workeragent.cpython-36.pyc +0 -0
  49. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/translate/mas/worker/translatetask.py +0 -0
  50. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/translate/mas/worker/workeragent.py +0 -0
  51. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/translate/migrations/__init__.py +0 -0
  52. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/translate/migrations/__pycache__/__init__.cpython-36.pyc +0 -0
  53. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/translate/models.py +0 -0
  54. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/translate/tests.py +0 -0
  55. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/translate/urls.py +0 -0
  56. {pbesa-4.0.7 → pbesa-4.0.9}/examples/django/helloworld/translate/views.py +0 -0
  57. {pbesa-4.0.7 → pbesa-4.0.9}/examples/remote/mas/controller/__pycache__/countercontroller.cpython-36.pyc +0 -0
  58. {pbesa-4.0.7 → pbesa-4.0.9}/examples/remote/mas/controller/__pycache__/counterdelegate.cpython-36.pyc +0 -0
  59. {pbesa-4.0.7 → pbesa-4.0.9}/examples/remote/mas/controller/__pycache__/counterresponse.cpython-36.pyc +0 -0
  60. {pbesa-4.0.7 → pbesa-4.0.9}/examples/remote/mas/controller/__pycache__/translatecontroller.cpython-36.pyc +0 -0
  61. {pbesa-4.0.7 → pbesa-4.0.9}/examples/remote/mas/controller/__pycache__/translatedelegate.cpython-36.pyc +0 -0
  62. {pbesa-4.0.7 → pbesa-4.0.9}/examples/remote/mas/controller/__pycache__/translateresponse.cpython-36.pyc +0 -0
  63. {pbesa-4.0.7 → pbesa-4.0.9}/examples/remote/mas/controller/countercontroller.py +0 -0
  64. {pbesa-4.0.7 → pbesa-4.0.9}/examples/remote/mas/controller/counterdelegate.py +0 -0
  65. {pbesa-4.0.7 → pbesa-4.0.9}/examples/remote/mas/controller/counterresponse.py +0 -0
  66. {pbesa-4.0.7 → pbesa-4.0.9}/examples/remote/mas/worker/__pycache__/counteragent.cpython-36.pyc +0 -0
  67. {pbesa-4.0.7 → pbesa-4.0.9}/examples/remote/mas/worker/__pycache__/countertask.cpython-36.pyc +0 -0
  68. {pbesa-4.0.7 → pbesa-4.0.9}/examples/remote/mas/worker/__pycache__/translatetask.cpython-36.pyc +0 -0
  69. {pbesa-4.0.7 → pbesa-4.0.9}/examples/remote/mas/worker/__pycache__/workeragent.cpython-36.pyc +0 -0
  70. {pbesa-4.0.7 → pbesa-4.0.9}/examples/remote/mas/worker/counteragent.py +0 -0
  71. {pbesa-4.0.7 → pbesa-4.0.9}/examples/remote/mas/worker/countertask.py +0 -0
  72. {pbesa-4.0.7 → pbesa-4.0.9}/examples/remote/remote_a.py +0 -0
  73. {pbesa-4.0.7 → pbesa-4.0.9}/examples/remote/remote_b.py +0 -0
  74. {pbesa-4.0.7 → pbesa-4.0.9}/examples/remote/remote_c.py +0 -0
  75. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/kernel/__init__.py +0 -0
  76. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/kernel/adapter.py +0 -0
  77. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/kernel/agent.py +0 -0
  78. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/kernel/io/__init__.py +0 -0
  79. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/kernel/io/system_file.py +0 -0
  80. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/kernel/io/tcp_server.py +0 -0
  81. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/kernel/res/__init__.py +0 -0
  82. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/kernel/res/__pycache__/__init__.cpython-36.pyc +0 -0
  83. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/kernel/res/__pycache__/__init__.cpython-37.pyc +0 -0
  84. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/kernel/res/__pycache__/__init__.cpython-38.pyc +0 -0
  85. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/kernel/res/__pycache__/__init__.cpython-39.pyc +0 -0
  86. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/kernel/res/conf.json +0 -0
  87. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/kernel/util.py +0 -0
  88. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/kernel/world.py +0 -0
  89. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/mas.py +0 -0
  90. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/models.py +0 -0
  91. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/remote/__init__.py +0 -0
  92. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/remote/adm_listener.py +0 -0
  93. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/remote/adm_listener_handler.py +0 -0
  94. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/remote/exceptions.py +0 -0
  95. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/remote/remote_adm.py +0 -0
  96. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/remote/remote_adm_handler.py +0 -0
  97. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/social/__init__.py +0 -0
  98. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/social/collaborative_team.py +0 -0
  99. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/social/delegator.py +0 -0
  100. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/social/delegator_team.py +0 -0
  101. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/social/dialog.py +0 -0
  102. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/social/selected_dispatcher_team.py +0 -0
  103. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/social/templates.py +0 -0
  104. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa/social/worker.py +0 -0
  105. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa.egg-info/dependency_links.txt +0 -0
  106. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa.egg-info/requires.txt +0 -0
  107. {pbesa-4.0.7 → pbesa-4.0.9}/pbesa.egg-info/top_level.txt +0 -0
  108. {pbesa-4.0.7 → pbesa-4.0.9}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pbesa
3
- Version: 4.0.7
3
+ Version: 4.0.9
4
4
  License-File: LICENSE
5
5
  License-File: LICENSE.txt
6
6
  Requires-Dist: pymongo==4.6.3
@@ -2,4 +2,5 @@ from .kernel import *
2
2
  from .social import *
3
3
  from .remote import *
4
4
  from .cognitive import *
5
- from .models import *
5
+ from .models import *
6
+ from .celulas import *
@@ -0,0 +1,3 @@
1
+ from .celula_casos import *
2
+ from .celula_consultas import *
3
+ from .celula_saludos import *
@@ -0,0 +1,60 @@
1
+ import logging
2
+
3
+ PROMPT = """
4
+ Eres un clasificador que identifica si un texto corresponde a una queja o demanda que debe ser radicada ante un ente de control del Estado colombiano.
5
+
6
+ Responde únicamente con:
7
+ - QUEJA_DEMANDA
8
+ - NO_QUEJA_DEMANDA
9
+
10
+ **Definición de QUEJA_DEMANDA**: El texto describe hechos, situaciones o infracciones por parte de una empresa, entidad o persona que pueden requerir la intervención de entidades como:
11
+
12
+ - Superintendencia de Sociedades
13
+ - Superintendencia de Industria y Comercio
14
+ - Supersalud
15
+ - Dirección General Marítima
16
+ - Superintendencia Financiera de Colombia
17
+ - Instituto Colombiano Agropecuario (ICA)
18
+ - Dirección Nacional de Derecho de Autor
19
+ - Autoridades de protección al consumidor
20
+ - Casos de competencia desleal o propiedad industrial
21
+
22
+ **NO_QUEJA_DEMANDA**: El texto no describe una inconformidad, infracción ni intención de denuncia. Puede ser una pregunta, saludo, comentario o solicitud de orientación.
23
+
24
+ ---
25
+
26
+ **Ejemplos:**
27
+
28
+ 1. "Quiero presentar una denuncia contra la empresa Colmédica por incumplimiento en la prestación de servicios de salud." → QUEJA_DEMANDA
29
+ 2. "La empresa Navemar ha incurrido en prácticas marítimas irregulares y omisión de protocolos de seguridad." → QUEJA_DEMANDA
30
+ 3. "Explícame cómo radicar una queja" → NO_QUEJA_DEMANDA
31
+ 4. "Hola, buen día" → NO_QUEJA_DEMANDA
32
+ 5. "Evacol S.A.S. está copiando diseños registrados de Crocs Inc. y aprovechando su reputación." → QUEJA_DEMANDA
33
+ 6. "¿Dónde puedo radicar una demanda?" → NO_QUEJA_DEMANDA
34
+ 7. "El supermercado está vendiendo productos vencidos que afectaron mi salud." → QUEJA_DEMANDA
35
+ 8. "Necesito orientación sobre propiedad industrial" → NO_QUEJA_DEMANDA
36
+
37
+ ---
38
+
39
+ Texto: "%s"
40
+
41
+ Clasificación:
42
+ """
43
+
44
+ # Efectua la inferencia del modelo.
45
+ def derive(service, text) -> any:
46
+ try:
47
+ logging.info(f"Procesando: {text}")
48
+ tmp_work_memory = []
49
+ prompt = PROMPT % text
50
+ tmp_work_memory.append({"role": "user", "content": prompt})
51
+ res = service.generate(tmp_work_memory)
52
+ logging.info(f"Respuesta: {res}")
53
+ if not res or res == "":
54
+ res = text
55
+ logging.warning(f"No obtener una respuesta.")
56
+ return res
57
+ except Exception as e:
58
+ logging.error(f"Error al procesar: {text}")
59
+ logging.error(e)
60
+ return None
@@ -0,0 +1,45 @@
1
+ import logging
2
+
3
+ PROMPT = """
4
+ Eres un clasificador de intenciones. Tu tarea es analizar el siguiente texto y determinar si representa una **pregunta** o **solicitud de información**.
5
+
6
+ Responde solo con:
7
+ - PREGUNTA_O_SOLICITUD
8
+ - NO_PREGUNTA
9
+
10
+ **Definiciones:**
11
+ - **PREGUNTA_O_SOLICITUD**: El texto expresa claramente una intención de obtener información, ya sea mediante una pregunta directa ("¿Qué hora es?") o una solicitud indirecta ("Quisiera saber el estado del pedido").
12
+ - **NO_PREGUNTA**: El texto no busca información. Puede ser un saludo, afirmación, comentario, instrucción, etc.
13
+
14
+ **Ejemplos:**
15
+ 1. "¿Cuál es el horario de atención?" → PREGUNTA_O_SOLICITUD
16
+ 2. "Necesito saber cómo ingresar al sistema" → PREGUNTA_O_SOLICITUD
17
+ 3. "Hola, buen día" → NO_PREGUNTA
18
+ 4. "Ya envié el informe" → NO_PREGUNTA
19
+ 5. "¿Me puedes confirmar la dirección?" → PREGUNTA_O_SOLICITUD
20
+ 6. "Saludos" → NO_PREGUNTA
21
+ 7. "Explícame cómo hacerlo" → PREGUNTA_O_SOLICITUD
22
+ 8. "No tengo acceso" → NO_PREGUNTA
23
+
24
+ Texto: "%s"
25
+
26
+ Clasificación:
27
+ """
28
+
29
+ # Efectua la inferencia del modelo.
30
+ def derive(service, text) -> any:
31
+ try:
32
+ logging.info(f"Procesando: {text}")
33
+ tmp_work_memory = []
34
+ prompt = PROMPT % text
35
+ tmp_work_memory.append({"role": "user", "content": prompt})
36
+ res = service.generate(tmp_work_memory)
37
+ logging.info(f"Respuesta: {res}")
38
+ if not res or res == "":
39
+ res = text
40
+ logging.warning(f"No obtener una respuesta.")
41
+ return res
42
+ except Exception as e:
43
+ logging.error(f"Error al procesar: {text}")
44
+ logging.error(e)
45
+ return None
@@ -0,0 +1,41 @@
1
+ import logging
2
+
3
+ PROMPT = """
4
+ Eres un clasificador de saludos. Tu tarea es analizar el siguiente texto y determinar si es un saludo.
5
+
6
+ Responde únicamente con una de estas opciones:
7
+ - SALUDO
8
+ - NO_SALUDO
9
+
10
+ **Definición de saludo**: Un saludo es cualquier forma de cortesía o expresión inicial utilizada para iniciar una conversación. Esto incluye "Hola", "Buenos días", "Qué tal", "Ey", "Saludos", etc., incluso si van acompañados de una pregunta o comentario breve. No se consideran saludos las preguntas o afirmaciones que van directo al contenido sin intención de cortesía.
11
+
12
+ Ejemplos:
13
+ - "Hola, ¿cómo estás?" → SALUDO
14
+ - "Buenos días, equipo" → SALUDO
15
+ - "¿Cómo se hace este análisis?" → NO_SALUDO
16
+ - "Ey, qué más" → SALUDO
17
+ - "Necesito ayuda con el código" → NO_SALUDO
18
+ - "Saludos" → SALUDO
19
+
20
+ Texto: "%s"
21
+
22
+ Clasificación:
23
+ """
24
+
25
+ # Efectua la inferencia del modelo.
26
+ def derive(service, text) -> any:
27
+ try:
28
+ logging.info(f"Procesando: {text}")
29
+ tmp_work_memory = []
30
+ prompt = PROMPT % text
31
+ tmp_work_memory.append({"role": "user", "content": prompt})
32
+ res = service.generate(tmp_work_memory)
33
+ logging.info(f"Respuesta: {res}")
34
+ if not res or res == "":
35
+ res = text
36
+ logging.warning(f"No obtener una respuesta.")
37
+ return res
38
+ except Exception as e:
39
+ logging.error(f"Error al procesar: {text}")
40
+ logging.error(e)
41
+ return None
@@ -0,0 +1,49 @@
1
+ import logging
2
+
3
+ PROMPT = """
4
+ Eres un clasificador de intenciones de texto. Debes analizar el texto proporcionado y clasificarlo en una de las siguientes categorías:
5
+
6
+ 1. SALUDO: El texto contiene un saludo inicial como "hola", "buen día", "buenas tardes", "qué tal", "saludos", etc.
7
+ 2. PREGUNTA_O_SOLICITUD: El texto busca obtener información, ya sea mediante una pregunta directa ("¿Qué hora es?") o una solicitud indirecta ("Necesito saber cómo ingresar").
8
+ 3. QUEJA_DEMANDA: El texto describe una inconformidad o denuncia que debe ser radicada ante un ente de control estatal, como la Superintendencia de Industria y Comercio, Supersalud, ICA, Dirección Nacional de Derecho de Autor, etc.
9
+ 4. NINGUNA: El texto no encaja en ninguna de las categorías anteriores.
10
+
11
+ Responde solo con una de estas cuatro categorías, en mayúsculas.
12
+
13
+ ---
14
+
15
+ **Ejemplos:**
16
+
17
+ - "Hola, buen día" → SALUDO
18
+ - "¿Dónde puedo radicar una queja?" → PREGUNTA_O_SOLICITUD
19
+ - "Quiero demandar a una empresa que está usando mi marca registrada" → QUEJA_DEMANDA
20
+ - "Ya envié el documento que solicitaste" → NINGUNA
21
+ - "Explícame cómo hacerlo" → PREGUNTA_O_SOLICITUD
22
+ - "Evacol S.A.S. está copiando diseños de Crocs Inc. para confundir a los consumidores" → QUEJA_DEMANDA
23
+ - "Saludos cordiales" → SALUDO
24
+ - "Estoy confirmando la reunión de mañana" → NINGUNA
25
+
26
+ ---
27
+
28
+ Texto: "%s"
29
+
30
+ Clasificación:
31
+ """
32
+
33
+ # Efectua la inferencia del modelo.
34
+ def derive(service, text) -> any:
35
+ try:
36
+ logging.info(f"Procesando: {text}")
37
+ tmp_work_memory = []
38
+ prompt = PROMPT % text
39
+ tmp_work_memory.append({"role": "user", "content": prompt})
40
+ res = service.generate(tmp_work_memory)
41
+ logging.info(f"Respuesta: {res}")
42
+ if not res or res == "":
43
+ res = text
44
+ logging.warning(f"No obtener una respuesta.")
45
+ return res
46
+ except Exception as e:
47
+ logging.error(f"Error al procesar: {text}")
48
+ logging.error(e)
49
+ return None
@@ -17,14 +17,16 @@ import uuid
17
17
  import json
18
18
  import logging
19
19
  import traceback
20
+ from .mas import Adm
20
21
  from pydantic import BaseModel
21
22
  from typing import List, Optional
22
23
  from abc import ABC, abstractmethod
24
+ from .celulas import celula_casos, celula_consultas, celula_saludos
23
25
  from pbesa.models import AIFoundry, AzureInference, GPTService, ServiceProvider
24
26
  from pbesa.social.dialog import (
25
27
  DialogState, imprimir_grafo, recorrer_interacciones, extraer_diccionario_nodos,
26
28
  ActionNode, DeclarativeNode, GotoNode) #, TerminalNode
27
- from pbesa.social.prompts import CLASSIFICATION_PROMPT, DERIVE_PROMPT, RECOVERY_PROMPT
29
+ from pbesa.social.prompts import CLASSIFICATION_PROMPT, DERIVE_PROMPT, RECOVERY_PROMPT, ADAPT_PROMPT
28
30
  # --------------------------------------------------------
29
31
  # Define DTOs
30
32
  # --------------------------------------------------------
@@ -481,7 +483,7 @@ class Dialog(ABC):
481
483
  "counter": 0
482
484
  }
483
485
  # Define recovery message
484
- self.RECOVERY_MSG = "Lo lamento, puedes darme más detalles o reformular"
486
+ 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."
485
487
  # Define vertices list
486
488
  self.__vertices = []
487
489
  # Define visited nodes
@@ -586,6 +588,9 @@ class Dialog(ABC):
586
588
  "performative": DialogState.START,
587
589
  "counter": 0
588
590
  }
591
+ # Reset visited nodes
592
+ self.__visited_nodes = 0
593
+ self.__vertices = []
589
594
 
590
595
  def notify(self, text):
591
596
  try:
@@ -611,6 +616,14 @@ class Dialog(ABC):
611
616
  canales = self.state['canales']
612
617
  canal = canales.get(team)
613
618
  if session_flag:
619
+ # Actualiza la sesion
620
+ session_manager = self.state['session_manager']
621
+ session_manager.update_session(self.state['session_id'], {
622
+ 'team': team,
623
+ 'owner': team,
624
+ 'performative': DialogState.START,
625
+ })
626
+ # Construye el mensaje
614
627
  dto = {
615
628
  "data": {
616
629
  'text': data,
@@ -690,57 +703,122 @@ class Dialog(ABC):
690
703
  }
691
704
  logging.info(f"Recovery attemps: {self.__recovery["counter"]}")
692
705
  # Verifica si se ha alcanzado el límite de recuperación
693
- if self.__recovery['counter'] <= 3 and self.__visited_nodes < 5:
694
- self.notify("identificando concepto...")
695
- #--------------------------
696
- # Verifica que exista la performativa
697
- if not dialog_state in self.__dfa:
698
- self.notify("concepto no encontrado")
699
- return self.recovery(query)
700
- # Performativa encontrada
701
- children = None
702
- self.notify("concepto encontrado")
703
- #--------------------------
704
- # Obtiene los hijos del nodo
705
- node = self.__dfa[dialog_state]
706
- if not isinstance(node, list):
707
- children = node.children
708
- else:
709
- # Es una lista de nodos
710
- children = node
711
- #--------------------------
712
- # Flujo de selección
706
+ if self.__recovery['counter'] <= 3 and self.__visited_nodes <= 3:
713
707
  select_node = None
714
- self.notify("flujo de seleccion...")
715
- if children and len(children)> 1:
716
- logging.info(f"--> Más de una opción.")
717
- options = ""
718
- cont = 1
719
- for item in children:
720
- options += f"{cont}) {item.text}\n"
721
- cont += 1
722
- prompt = CLASSIFICATION_PROMPT % (query, options)
723
- logging.info(f"Query: {query},\n Options:\n{options}")
724
- self.__meta_work_memory.append({"role": "user", "content": prompt})
725
- res = self.__ai_service.generate(self.__meta_work_memory)
726
- logging.info(f"Thought: {res}")
727
- self.__meta_work_memory = []
728
- res = self.get_text(res)
729
- for option in range(1, cont):
730
- if str(option) in res:
731
- select_node = children[option-1]
732
- logging.info(f"Select node: {select_node.text}")
733
- break
734
- if not select_node:
735
- logging.info("=> No se seleccionó ninguna opción")
708
+ #------------------------------
709
+ # Flujode de excepcion
710
+ #------------------------------
711
+ if owner == "Web" and dialog_state == DialogState.START:
712
+ logging.info(f"TOPTQ: {owner} - {dialog_state} - {team_source} - {query}")
713
+ logging.info(f"------------Flujo de excepcion---------------")
714
+ self.notify("identificando intencion...")
715
+ # Obtiene discriminadores
716
+ caso = celula_casos.derive(self.__ai_service, query)
717
+ consulta = celula_consultas.derive(self.__ai_service, query)
718
+ saludo = celula_saludos.derive(self.__ai_service, query)
719
+ # 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"
723
+ # Verifica los casos
724
+ dicriminador = "Ninguno"
725
+ if es_saludo or es_consulta or es_caso:
726
+ logging.info("Sin ambiguedad")
727
+ self.notify("discriminando...")
728
+ if es_saludo:
729
+ dicriminador = "saluda"
730
+ elif es_consulta:
731
+ dicriminador = "consulta"
732
+ elif es_caso:
733
+ dicriminador = "caso"
734
+ else:
735
+ logging.info("Hay ambiguedad")
736
+ self.notify("identificando ambiguedad...")
737
+ if saludo == "SALUDO":
738
+ dicriminador = "saluda"
739
+ else:
740
+ dicriminador = "consulta"
741
+ #--------------------------
742
+ # Obtiene los hijos del
743
+ # nodo
744
+ children = None
745
+ node = self.__dfa[dialog_state]
746
+ if not isinstance(node, list):
747
+ children = node.children
748
+ else:
749
+ # Es una lista de nodos
750
+ children = node
751
+ #--------------------------
752
+ # Flujo de selección
753
+ self.notify("flujo de seleccion...")
754
+ if children and len(children)> 1:
755
+ logging.info(f"--> Más de una opción.")
756
+ options = ""
757
+ cont = 1
758
+ for item in children:
759
+ if dicriminador in item.text:
760
+ select_node = item
761
+ break
762
+ else:
763
+ #------------------------------
764
+ # Fulo normal
765
+ #------------------------------
766
+ logging.info("Flujo normal")
767
+ self.notify("identificando concepto...")
768
+ #----------------------
769
+ # Verifica que exista
770
+ # la performativa
771
+ if not dialog_state in self.__dfa:
772
+ self.notify("concepto no encontrado")
773
+ return self.recovery(query)
774
+ # Performativa encontrada
775
+ children = None
776
+ self.notify("concepto encontrado")
777
+ #----------------------
778
+ # Obtiene los hijos del
779
+ # nodo
780
+ node = self.__dfa[dialog_state]
781
+ if not isinstance(node, list):
782
+ children = node.children
783
+ else:
784
+ # Es una lista de nodos
785
+ children = node
786
+ #----------------------
787
+ # Flujo de selección
788
+ select_node = None
789
+ self.notify("flujo de seleccion...")
790
+ if children and len(children)> 1:
791
+ logging.info(f"--> Más de una opción.")
792
+ options = ""
793
+ cont = 1
794
+ for item in children:
795
+ options += f"{cont}) {item.text}\n"
796
+ cont += 1
797
+ prompt = CLASSIFICATION_PROMPT % (query, options)
798
+ logging.info(f"Query: {query},\n Options:\n{options}")
799
+ self.__meta_work_memory.append({"role": "user", "content": prompt})
800
+ res = self.__ai_service.generate(self.__meta_work_memory)
801
+ logging.info(f"Thought: {res}")
802
+ self.__meta_work_memory = []
803
+ res = self.get_text(res)
804
+ for option in range(1, cont):
805
+ if str(option) in res:
806
+ select_node = children[option-1]
807
+ logging.info(f"Select node: {select_node.text}")
808
+ break
809
+ if not select_node:
810
+ logging.info("=> No se seleccionó ninguna opción")
811
+ select_node = children[0]
812
+ logging.info(f"=> Selecciona el primer nodo: {select_node.text}")
813
+ elif children and len(children) == 1:
814
+ logging.info(f"--> Una opción.")
736
815
  select_node = children[0]
737
- logging.info(f"=> Selecciona el primer nodo: {select_node.text}")
738
- elif children and len(children) == 1:
739
- logging.info(f"--> Una opción.")
740
- select_node = children[0]
741
- else:
742
- logging.info("???> Es un nodo terminal o iniciador")
743
- return self.recovery(query)
816
+ else:
817
+ logging.info("???> Es un nodo terminal o iniciador")
818
+ logging.warning(f"???> Es un nodo terminal o iniciador: {node.text}")
819
+ logging.warning(f"???> Es un nodo terminal o iniciador: {node.performative}")
820
+ return self.recovery(query)
821
+
744
822
  #--------------------------
745
823
  # Verifica si es un nodo
746
824
  # que ya fue recorrido
@@ -764,7 +842,20 @@ class Dialog(ABC):
764
842
  # Efectua transicion
765
843
  if select_node:
766
844
  res = select_node.text
767
- node = select_node.children[0]
845
+ if select_node.children and len(select_node.children) > 0:
846
+ res = select_node.children[0].text
847
+ node = select_node.children[0]
848
+ else:
849
+ logging.info(f"-> El nodo de transición es terminal: {select_node.text}")
850
+ res = select_node.text
851
+ node = select_node
852
+ else:
853
+ logging.info(f"-> !!!!!!!!!!!!!! Concepto no encontrado !!!!!!!!!!!!!!")
854
+ if isinstance(node, list) and len(node) > 0:
855
+ node = node[0]
856
+ else:
857
+ logging.info(f"-> !!!!!!!!!!!!!! Concepto no encontrado ????????????????")
858
+ return self.recovery(query)
768
859
  logging.info(f"Flujo normal: {res}")
769
860
  self.notify(res)
770
861
  #---------------------------
@@ -780,9 +871,12 @@ class Dialog(ABC):
780
871
  # trabajo
781
872
  if team_source:
782
873
  self.__work_memory.append({"role": "user", "content": res})
874
+ logging.info(f"-> Actualiza WM: {res}")
783
875
  else:
784
876
  self.__work_memory.append({"role": "user", "content": query})
785
- self.__work_memory.append({"role": "user", "content": res})
877
+ #self.__work_memory.append({"role": "user", "content": res})
878
+ logging.info(f"-> Actualiza q-WM: {query}")
879
+ #logging.info(f"-> Actualiza r-WM: {res}")
786
880
  #---------------------------
787
881
  # Efectua inferencia
788
882
  new_owner, new_dialog_state, res, team = self.do_transition(owner, node, query)
@@ -839,16 +933,22 @@ class Dialog(ABC):
839
933
  if node.is_terminal:
840
934
  logging.info(f"-> node team -> es terminal -> {node.text}")
841
935
  self.__work_memory.append({"role": "user", "content": node.text})
842
- logging.info("-----")
843
- logging.info("\n%s", json.dumps(self.__work_memory, indent=4))
844
- logging.info("-----")
845
- res = self.__ai_service.generate(self.__work_memory)
846
- res = self.get_text(res)
847
- self.__work_memory.append({"role": "system", "content": res})
848
- # Check if res is empty
849
- if not res or res == "":
850
- self.notify(f"no pude contactar al agente: {node.team}")
851
- return self.recovery(query)
936
+
937
+ res = query
938
+ if "consulta" in node.text.lower():
939
+ logging.info(f"-> node team -> consulta: {query}")
940
+ else:
941
+ logging.info("-----")
942
+ logging.info("\n%s", json.dumps(self.__work_memory, indent=4))
943
+ logging.info("-----")
944
+ res = self.__ai_service.generate(self.__work_memory)
945
+ res = self.get_text(res)
946
+ self.__work_memory.append({"role": "system", "content": res})
947
+ # Check if res is empty
948
+ if not res or res == "":
949
+ self.notify(f"no pude contactar al agente: {node.team}")
950
+ return self.recovery(query)
951
+
852
952
  self.notify(f"le envio al agente {node.team}: {res}")
853
953
  logging.info(f"-> node team -> envia: {res}")
854
954
  res = self.team_inquiry(node.team, res, None, True)
@@ -860,11 +960,27 @@ class Dialog(ABC):
860
960
  else:
861
961
  return self.recovery(query)
862
962
  else:
963
+
863
964
  logging.info("-> node team -> continua")
864
- self.__work_memory.append({"role": "user", "content": node.text})
865
- logging.info(f"-> node team -> envia: {query}")
866
- res = self.team_inquiry(node.team, query, node.tool, False)
965
+ self.__work_memory.append({"role": "user", "content": node.text})
966
+ res = query
967
+ if "consulta" in node.text.lower():
968
+ logging.info(f"-> node team -> consulta: {query}")
969
+ else:
970
+ logging.info(f"-> node team -> sentencia: {node.text}")
971
+ logging.info("-----")
972
+ logging.info("\n%s", json.dumps(self.__work_memory, indent=4))
973
+ logging.info("-----")
974
+ res = self.get_text(res)
975
+ self.__work_memory.append({"role": "system", "content": res})
976
+ # Check if res is empty
977
+ if not res or res == "":
978
+ self.notify(f"no pude contactar al agente: {node.team}")
979
+ return self.recovery(query)
980
+ self.notify(f"le envio al agente {node.team}: {res}")
981
+ res = self.team_inquiry(node.team, res, node.tool, False)
867
982
  self.notify(f"continuando con díalogo")
983
+
868
984
  # Adiciona el texto al work memory
869
985
  if res and not res == "ERROR" and not res == "":
870
986
  logging.info(f"-> Adicion WM node team -> text: {res}")
@@ -908,8 +1024,10 @@ class Dialog(ABC):
908
1024
  self.notify(f"finalizando díalogo de inferencia")
909
1025
  logging.info(f"Tipe node: {type(node)}")
910
1026
  logging.info(f"$$$> new_owner: {owner} new_dialog_state: {new_dialog_state}")
1027
+ #logging.info(f"------------RESET---------------")
1028
+ #self.reset()
911
1029
  self.notify("STOP")
912
- return owner, new_dialog_state, res, owner
1030
+ return "Web", DialogState.START, res, "Web"
913
1031
  logging.info("END: do_transition")
914
1032
  except Exception as e:
915
1033
  traceback.print_exc()
@@ -923,4 +1041,112 @@ class Dialog(ABC):
923
1041
  :param query: query
924
1042
  :return: str
925
1043
  """
926
- self.knowledge = knowledge
1044
+ self.knowledge = knowledge
1045
+
1046
+ def adapt(self, data, profile) -> any:
1047
+ """ Adapt method
1048
+ :param data: data
1049
+ :return: str
1050
+ """
1051
+ try:
1052
+ logging.info(f"Adaptando respuesta: {data}")
1053
+ # Get text
1054
+ text = ""
1055
+ if isinstance(data, str):
1056
+ text = data
1057
+ elif isinstance(data, dict):
1058
+ text = data['dto']['text'] if data and 'dto' in data and data['dto']['text'] is not None else ''
1059
+ else:
1060
+ raise ValueError("Respuesta mal formada")
1061
+ # Adapt the data
1062
+ tmp_work_memory = []
1063
+ prompt = ADAPT_PROMPT % (text, profile)
1064
+ tmp_work_memory.append({"role": "user", "content": prompt})
1065
+ res = self.__ai_service.generate(tmp_work_memory)
1066
+ res = self.get_text(res)
1067
+ logging.info(f"Respuesta adaptada: {res}")
1068
+ if not res or res == "":
1069
+ res = text
1070
+ logging.warning(f"No se pudo adaptar la respuesta.")
1071
+ return res
1072
+ except Exception as e:
1073
+ logging.error(f"Error al adaptar el dato: {data}")
1074
+ logging.error(e)
1075
+ return None
1076
+
1077
+ # --------------------------------------------------------
1078
+ # Define Special Dispatch
1079
+ # --------------------------------------------------------
1080
+
1081
+ class SpecialDispatch():
1082
+ """ Special dispatch """
1083
+
1084
+ def __init__(self) -> None:
1085
+ """ Constructor method """
1086
+ self.model:any = None
1087
+ self.model_conf:dict = None
1088
+ self.__meta_work_memory:list = []
1089
+ # Define AI service
1090
+ self.__ai_service = None
1091
+ self.knowledge = None
1092
+ # Define options dictionary
1093
+ self.__options_dict = {}
1094
+ # Reference of ADM
1095
+ self.adm = Adm()
1096
+
1097
+ def load_model(self, provider, config, ai_service=None) -> None:
1098
+ self.__service_provider, service = define_service_provider(provider, ai_service)
1099
+ service.setup(config)
1100
+ self.__ai_service = service
1101
+ # Setup options dictionary
1102
+ agent_list = self.get_agent_list()
1103
+ # Get the agent asocciated with the data.
1104
+ for agent_id in agent_list:
1105
+ agent = self.adm.get_agent(agent_id)
1106
+ # Check if the agent is instance of Dialog
1107
+ if isinstance(agent, Dialog):
1108
+ # Get the role
1109
+ role = agent.get_role()
1110
+ self.__options_dict[agent_id] = role.description
1111
+
1112
+ def get_text(self, mensaje) -> str:
1113
+ if mensaje:
1114
+ mensaje_limpio = mensaje.replace("<|im_start|>user<|im_sep|>", "").replace("<|im_start|>system<|im_sep|>", "") \
1115
+ .replace("<|im_start|>", "").replace("<|im_sep|>", "").replace("<|im_end|>", "") \
1116
+ .replace("[Usuario]: ", "").replace("[Sistema]: ", "") \
1117
+ .replace("<|user|>", "").replace("<|system|>", "")
1118
+ return mensaje_limpio.strip()
1119
+ else:
1120
+ return ""
1121
+
1122
+ def special_dispatch(self, data: any) -> None:
1123
+ """
1124
+ Response.
1125
+ @param data Event data
1126
+ """
1127
+ logging.info("Despachando por descripcion...")
1128
+ options = ""
1129
+ cont = 1
1130
+ agent_options = {}
1131
+ for agent, item in self.__options_dict.items():
1132
+ agent_options[cont] = agent
1133
+ options += f"{cont}) {item}\n"
1134
+ cont += 1
1135
+ query = data['dto']['text'] if data and 'dto' in data and data['dto']['text'] is not None else ''
1136
+ prompt = CLASSIFICATION_PROMPT % (query, options)
1137
+ logging.info(f"Query: {query},\n Options:\n{options}")
1138
+ self.__meta_work_memory.append({"role": "user", "content": prompt})
1139
+ res = self.__ai_service.generate(self.__meta_work_memory)
1140
+ logging.info(f"Thought: {res}")
1141
+ self.__meta_work_memory = []
1142
+ res = self.get_text(res)
1143
+ select_agent = None
1144
+ for option in range(1, cont+1):
1145
+ if str(option) in res:
1146
+ select_agent = agent_options[option]
1147
+ logging.info(f"Descripcion del agente seleccionado: {select_agent}")
1148
+ break
1149
+ if not select_agent:
1150
+ logging.info("=> No se seleccionó ningun agente")
1151
+ return select_agent
1152
+
@@ -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
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pbesa
3
- Version: 4.0.7
3
+ Version: 4.0.9
4
4
  License-File: LICENSE
5
5
  License-File: LICENSE.txt
6
6
  Requires-Dist: pymongo==4.6.3
@@ -70,6 +70,11 @@ pbesa.egg-info/SOURCES.txt
70
70
  pbesa.egg-info/dependency_links.txt
71
71
  pbesa.egg-info/requires.txt
72
72
  pbesa.egg-info/top_level.txt
73
+ pbesa/celulas/__init__.py
74
+ pbesa/celulas/celula_casos.py
75
+ pbesa/celulas/celula_consultas.py
76
+ pbesa/celulas/celula_saludos.py
77
+ pbesa/celulas/web.py
73
78
  pbesa/kernel/__init__.py
74
79
  pbesa/kernel/adapter.py
75
80
  pbesa/kernel/agent.py
@@ -4,7 +4,7 @@ from setuptools import setup, find_packages
4
4
 
5
5
  setup(
6
6
  name='pbesa',
7
- version='4.0.7',
7
+ version='4.0.9',
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