pbesa 4.0.28__tar.gz → 4.0.29__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 (120) hide show
  1. {pbesa-4.0.28 → pbesa-4.0.29}/PKG-INFO +1 -1
  2. pbesa-4.0.29/pbesa/celulas/celula_conversador.py +60 -0
  3. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/celulas/celula_datos_identificables.py +1 -1
  4. pbesa-4.0.29/pbesa/celulas/celula_evaluador.py +59 -0
  5. pbesa-4.0.29/pbesa/celulas/celula_extraccion.py +51 -0
  6. pbesa-4.0.29/pbesa/celulas/celula_parafraseo.py +56 -0
  7. pbesa-4.0.29/pbesa/celulas/celula_respuesta.py +58 -0
  8. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/celulas/celula_saludos.py +1 -1
  9. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/cognitive.py +141 -7
  10. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/social/dispatcher_team.py +4 -1
  11. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa.egg-info/PKG-INFO +1 -1
  12. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa.egg-info/SOURCES.txt +5 -0
  13. {pbesa-4.0.28 → pbesa-4.0.29}/setup.py +1 -1
  14. {pbesa-4.0.28 → pbesa-4.0.29}/.gitignore +0 -0
  15. {pbesa-4.0.28 → pbesa-4.0.29}/LICENSE +0 -0
  16. {pbesa-4.0.28 → pbesa-4.0.29}/LICENSE.txt +0 -0
  17. {pbesa-4.0.28 → pbesa-4.0.29}/MANIFEST +0 -0
  18. {pbesa-4.0.28 → pbesa-4.0.29}/README.md +0 -0
  19. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/db.sqlite3 +0 -0
  20. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/helloworld/__init__.py +0 -0
  21. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/helloworld/__pycache__/__init__.cpython-36.pyc +0 -0
  22. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/helloworld/__pycache__/pbesa.cpython-36.pyc +0 -0
  23. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/helloworld/__pycache__/settings.cpython-36.pyc +0 -0
  24. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/helloworld/__pycache__/urls.cpython-36.pyc +0 -0
  25. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/helloworld/__pycache__/wsgi.cpython-36.pyc +0 -0
  26. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/helloworld/asgi.py +0 -0
  27. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/helloworld/pbesa.py +0 -0
  28. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/helloworld/settings.py +0 -0
  29. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/helloworld/urls.py +0 -0
  30. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/helloworld/wsgi.py +0 -0
  31. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/manage.py +0 -0
  32. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/translate/__init__.py +0 -0
  33. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/translate/__pycache__/__init__.cpython-36.pyc +0 -0
  34. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/translate/__pycache__/admin.cpython-36.pyc +0 -0
  35. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/translate/__pycache__/apps.cpython-36.pyc +0 -0
  36. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/translate/__pycache__/models.cpython-36.pyc +0 -0
  37. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/translate/__pycache__/urls.cpython-36.pyc +0 -0
  38. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/translate/__pycache__/views.cpython-36.pyc +0 -0
  39. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/translate/admin.py +0 -0
  40. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/translate/apps.py +0 -0
  41. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/translate/mas/controller/__pycache__/translatecontroller.cpython-36.pyc +0 -0
  42. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/translate/mas/controller/__pycache__/translatedelegate.cpython-36.pyc +0 -0
  43. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/translate/mas/controller/__pycache__/translateresponse.cpython-36.pyc +0 -0
  44. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/translate/mas/controller/translatecontroller.py +0 -0
  45. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/translate/mas/controller/translatedelegate.py +0 -0
  46. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/translate/mas/controller/translateresponse.py +0 -0
  47. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/translate/mas/worker/__pycache__/translatetask.cpython-36.pyc +0 -0
  48. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/translate/mas/worker/__pycache__/workeragent.cpython-36.pyc +0 -0
  49. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/translate/mas/worker/translatetask.py +0 -0
  50. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/translate/mas/worker/workeragent.py +0 -0
  51. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/translate/migrations/__init__.py +0 -0
  52. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/translate/migrations/__pycache__/__init__.cpython-36.pyc +0 -0
  53. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/translate/models.py +0 -0
  54. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/translate/tests.py +0 -0
  55. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/translate/urls.py +0 -0
  56. {pbesa-4.0.28 → pbesa-4.0.29}/examples/django/helloworld/translate/views.py +0 -0
  57. {pbesa-4.0.28 → pbesa-4.0.29}/examples/remote/mas/controller/__pycache__/countercontroller.cpython-36.pyc +0 -0
  58. {pbesa-4.0.28 → pbesa-4.0.29}/examples/remote/mas/controller/__pycache__/counterdelegate.cpython-36.pyc +0 -0
  59. {pbesa-4.0.28 → pbesa-4.0.29}/examples/remote/mas/controller/__pycache__/counterresponse.cpython-36.pyc +0 -0
  60. {pbesa-4.0.28 → pbesa-4.0.29}/examples/remote/mas/controller/__pycache__/translatecontroller.cpython-36.pyc +0 -0
  61. {pbesa-4.0.28 → pbesa-4.0.29}/examples/remote/mas/controller/__pycache__/translatedelegate.cpython-36.pyc +0 -0
  62. {pbesa-4.0.28 → pbesa-4.0.29}/examples/remote/mas/controller/__pycache__/translateresponse.cpython-36.pyc +0 -0
  63. {pbesa-4.0.28 → pbesa-4.0.29}/examples/remote/mas/controller/countercontroller.py +0 -0
  64. {pbesa-4.0.28 → pbesa-4.0.29}/examples/remote/mas/controller/counterdelegate.py +0 -0
  65. {pbesa-4.0.28 → pbesa-4.0.29}/examples/remote/mas/controller/counterresponse.py +0 -0
  66. {pbesa-4.0.28 → pbesa-4.0.29}/examples/remote/mas/worker/__pycache__/counteragent.cpython-36.pyc +0 -0
  67. {pbesa-4.0.28 → pbesa-4.0.29}/examples/remote/mas/worker/__pycache__/countertask.cpython-36.pyc +0 -0
  68. {pbesa-4.0.28 → pbesa-4.0.29}/examples/remote/mas/worker/__pycache__/translatetask.cpython-36.pyc +0 -0
  69. {pbesa-4.0.28 → pbesa-4.0.29}/examples/remote/mas/worker/__pycache__/workeragent.cpython-36.pyc +0 -0
  70. {pbesa-4.0.28 → pbesa-4.0.29}/examples/remote/mas/worker/counteragent.py +0 -0
  71. {pbesa-4.0.28 → pbesa-4.0.29}/examples/remote/mas/worker/countertask.py +0 -0
  72. {pbesa-4.0.28 → pbesa-4.0.29}/examples/remote/remote_a.py +0 -0
  73. {pbesa-4.0.28 → pbesa-4.0.29}/examples/remote/remote_b.py +0 -0
  74. {pbesa-4.0.28 → pbesa-4.0.29}/examples/remote/remote_c.py +0 -0
  75. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/__init__.py +0 -0
  76. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/celulas/__init__.py +0 -0
  77. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/celulas/celula_casos.py +0 -0
  78. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/celulas/celula_consultas.py +0 -0
  79. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/celulas/celula_expertos.py +0 -0
  80. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/celulas/celula_generar_documento.py +0 -0
  81. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/celulas/celula_pertinencia.py +0 -0
  82. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/celulas/celula_preguntas.py +0 -0
  83. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/celulas/celula_simulador_ciudadano.py +0 -0
  84. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/celulas/data_extraction_cel.py +0 -0
  85. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/celulas/web.py +0 -0
  86. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/kernel/__init__.py +0 -0
  87. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/kernel/adapter.py +0 -0
  88. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/kernel/agent.py +0 -0
  89. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/kernel/io/__init__.py +0 -0
  90. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/kernel/io/system_file.py +0 -0
  91. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/kernel/io/tcp_server.py +0 -0
  92. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/kernel/res/__init__.py +0 -0
  93. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/kernel/res/__pycache__/__init__.cpython-36.pyc +0 -0
  94. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/kernel/res/__pycache__/__init__.cpython-37.pyc +0 -0
  95. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/kernel/res/__pycache__/__init__.cpython-38.pyc +0 -0
  96. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/kernel/res/__pycache__/__init__.cpython-39.pyc +0 -0
  97. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/kernel/res/conf.json +0 -0
  98. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/kernel/util.py +0 -0
  99. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/kernel/world.py +0 -0
  100. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/mas.py +0 -0
  101. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/models.py +0 -0
  102. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/remote/__init__.py +0 -0
  103. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/remote/adm_listener.py +0 -0
  104. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/remote/adm_listener_handler.py +0 -0
  105. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/remote/exceptions.py +0 -0
  106. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/remote/remote_adm.py +0 -0
  107. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/remote/remote_adm_handler.py +0 -0
  108. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/social/__init__.py +0 -0
  109. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/social/collaborative_team.py +0 -0
  110. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/social/delegator.py +0 -0
  111. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/social/delegator_team.py +0 -0
  112. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/social/dialog.py +0 -0
  113. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/social/prompts.py +0 -0
  114. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/social/selected_dispatcher_team.py +0 -0
  115. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/social/templates.py +0 -0
  116. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa/social/worker.py +0 -0
  117. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa.egg-info/dependency_links.txt +0 -0
  118. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa.egg-info/requires.txt +0 -0
  119. {pbesa-4.0.28 → pbesa-4.0.29}/pbesa.egg-info/top_level.txt +0 -0
  120. {pbesa-4.0.28 → pbesa-4.0.29}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pbesa
3
- Version: 4.0.28
3
+ Version: 4.0.29
4
4
  License-File: LICENSE
5
5
  License-File: LICENSE.txt
6
6
  Requires-Dist: pymongo>=4.6.3
@@ -0,0 +1,60 @@
1
+ import logging
2
+
3
+ SYSTEM_PROMPT = """
4
+ [ROL Y OBJETIVO]
5
+ Eres un asistente conversacional amigable y servicial llamado Justino especializado en las funciones jurisdiccionales de las entidades SIC, DIMAR, DNDA, SFC, SNS, ICA y Supersociedades.
6
+
7
+ Tu objetivo es analizar el historial de la conversación y las reglas para identificar qué información falta y luego formular una pregunta clara y natural al usuario.
8
+
9
+ [DEFINICIONES DE REFERENCIA]
10
+ %s
11
+
12
+ [REGLAS]
13
+ %s
14
+
15
+ [HISTORIAL DE LA CONVERSACIÓN]
16
+ %s
17
+
18
+ [TAREA]
19
+ Sigue un proceso de Chain of Thought para construir tu respuesta. Primero, razona sobre la información que tienes y la que te falta. Luego, escribe la pregunta final para el usuario.
20
+
21
+ [FORMATO DE RESPUESTA]
22
+ **Chain of Thought:**
23
+ 1. **Información disponible:** (Resume los datos que el usuario ya ha proporcionado).
24
+ 2. **Información requerida por las reglas:** (Enumera los datos que necesitas para validar todas las reglas).
25
+ 3. **Análisis de carencias:** (Compara la información disponible con la requerida para identificar exactamente qué falta).
26
+ 4. **Formulación de la pregunta:** (Diseña una pregunta amigable y precisa basada en el análisis de carencias).
27
+
28
+ [RESTRICCIONES]
29
+ - No debes proporcionar respuestas directas o afirmaciones, solo preguntas.
30
+ - La pregunta debe ser clara y natural, evitando tecnicismos innecesarios.
31
+ - No debes asumir información que no esté explícitamente en el historial de la conversación.
32
+ - Si el usario responde con una pregunta o comentario que no es relevante, debes ignorarlo y centrarte en la información que falta.
33
+
34
+ """
35
+
36
+ USER_PROMPT = """
37
+
38
+ **Respuesta final para el usuario:**
39
+ (Escribe aquí únicamente la pregunta que le harás al usuario).
40
+ """
41
+
42
+ # Efectua la inferencia del modelo.
43
+ def derive(service, definiciones, reglas, text, max_tkns=2000) -> any:
44
+ try:
45
+ tmp_work_memory = []
46
+ prompt = SYSTEM_PROMPT % (definiciones, reglas, text)
47
+ tmp_work_memory.append({"role": "system", "content": prompt})
48
+ prompt = USER_PROMPT
49
+ tmp_work_memory.append({"role": "user", "content": prompt})
50
+ res = service.generate(tmp_work_memory, max_tokens=max_tkns)
51
+ logging.info(f"\n\n\nProcesando:\nDefiniciones: {definiciones}\nReglas: {reglas}\nTexto: {text}")
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
@@ -31,7 +31,7 @@ Responde únicamente con:
31
31
  """
32
32
 
33
33
  # Efectua la inferencia del modelo.
34
- def derive(service, text, max_tkns=4096) -> any:
34
+ def derive(service, text, max_tkns=2000) -> any:
35
35
  try:
36
36
  tmp_work_memory = []
37
37
  user_prompt = """
@@ -0,0 +1,59 @@
1
+ import logging
2
+
3
+ SYSTEM_PROMPT = """
4
+ [TAREA]
5
+ Eres un sistema de clasificación experto. Tu única tarea es evaluar la siguiente conversación contra las reglas proporcionadas y responder con una sola palabra que resuma el estado.
6
+
7
+ [DEFINICIONES]
8
+ %s
9
+
10
+ [REGLAS]
11
+ %s
12
+
13
+ [INSTRUCCIONES DE RESPUESTA]
14
+ Responde únicamente con una de estas tres opciones:
15
+ - APLICA: Si la conversación contiene TODA la información necesaria para verificar las reglas, y AL MENOS UNA de las regla se cumple.
16
+ - RECHAZO: Si la conversación contiene información que viola explícitamente a TODAS las reglas.
17
+ - PREGUNTAR: Si en la conversación FALTA información esencial para poder verificar una o más reglas.
18
+
19
+ [EJEMPLOS]
20
+ Reglas:
21
+ - Ser mayor de 18
22
+ - Vivir en México.
23
+
24
+ Texto del usuario:
25
+ - Texto: "Tengo 20 años y vivo en la Ciudad de México." -> APLICA
26
+ - Texto: "Tengo 12 y vivo en Argentina." -> RECHAZO
27
+ - Texto: "Soy de México." -> APLICA
28
+ - Texto: "Soy hombre." -> PREGUNTAR
29
+
30
+ """
31
+
32
+ USER_PROMPT = """
33
+
34
+ [EVALUACIÓN ACTUAL]
35
+ Conversación:
36
+ "%s"
37
+
38
+ Respuesta:
39
+ """
40
+
41
+ # Efectua la inferencia del modelo.
42
+ def derive(service, definiciones, reglas, text, max_tkns=2000) -> any:
43
+ try:
44
+ tmp_work_memory = []
45
+ prompt = SYSTEM_PROMPT % (definiciones, reglas)
46
+ tmp_work_memory.append({"role": "system", "content": prompt})
47
+ prompt = USER_PROMPT % text
48
+ tmp_work_memory.append({"role": "user", "content": prompt})
49
+ res = service.generate(tmp_work_memory, max_tokens=max_tkns)
50
+ logging.info(f"\n\n\nProcesando:\nDefiniciones: {definiciones}\nReglas: {reglas}\nTexto: {text}")
51
+ logging.info(f"Respuesta: {res}")
52
+ if not res or res == "":
53
+ res = text
54
+ logging.warning(f"No obtener una respuesta.")
55
+ return res
56
+ except Exception as e:
57
+ logging.error(f"Error al procesar: {text}")
58
+ logging.error(e)
59
+ return None
@@ -0,0 +1,51 @@
1
+ import logging
2
+
3
+ SYSTEM_PROMPT = """
4
+ Eres un extractor de datos estructurados.
5
+ Tu tarea es leer la **Descripción** (lo que se le pide al usuario) y la **Respuesta del usuario** y devolver **únicamente** un objeto JSON válido con las claves indicadas en la descripción y los valores dados por el usuario.
6
+
7
+ Reglas:
8
+ 1. Usa exactamente el texto entre comillas o negritas de la descripción como nombre de la clave en el JSON.
9
+ • Ej.: si la descripción contiene **"Tipo de solicitante"**, la clave debe ser `"Tipo de solicitante"`.
10
+ 2. El valor debe ser la respuesta del usuario:
11
+ • Elimina saltos de línea y espacios al principio/fin.
12
+ • Respeta mayúsculas/minúsculas tal cual la escribió el usuario.
13
+ • Si responde varias opciones separadas (por comas, saltos de línea, “y”, etc.), devuelve una lista de cadenas.
14
+ 3. Si falta información para alguna clave, pon el valor vacío: `""`.
15
+ 4. No añadas texto extra, explicaciones ni código. Devuelve **solo** el objeto JSON.
16
+
17
+ Descripción:
18
+ \"\"\"%s\"\"\"
19
+
20
+ """
21
+ USER_PROMPT = """
22
+ Respuesta del usuario:
23
+ \"\"\"%s\"\"\"
24
+
25
+ Salida JSON:
26
+ """
27
+
28
+ # Efectua la inferencia del modelo.
29
+ def derive(service, query, max_tkns=2000) -> any:
30
+ try:
31
+ description = query.get("description", "")
32
+ text = query.get("text", "")
33
+
34
+ tmp_work_memory = []
35
+ prompt = SYSTEM_PROMPT
36
+ tmp_work_memory.append({"role": "system", "content": prompt})
37
+ prompt = USER_PROMPT % description
38
+ tmp_work_memory.append({"role": "user", "content": text})
39
+
40
+ res = service.generate(tmp_work_memory, max_tokens=max_tkns)
41
+
42
+ logging.info(f"[Celula][Extrac][Procesando]: {text}")
43
+ logging.info(f"[Celula][Extrac][Respuesta]: {res}")
44
+ if not res or res == "":
45
+ res = text
46
+ logging.warning(f"[Celula][Extrac]: No obtener una respuesta.")
47
+ return res.replace("*", "").strip()
48
+ except Exception as e:
49
+ logging.error(f"[Celula][Extrac]: Error al procesar: {text}")
50
+ logging.error(e)
51
+ return None
@@ -0,0 +1,56 @@
1
+ import logging
2
+
3
+ SYSTEM_PROMPT = """
4
+ Dado el siguiente 'Conocimiento' y la 'Consulta de usuario', tu tarea es responder de manera amable y en lenguaje natural.
5
+
6
+ **Conocimiento:**
7
+ %s
8
+
9
+ **Consulta de usuario:**
10
+ %s
11
+
12
+ **Importante:**
13
+ - Es fundamental que evites responder si la consulta del usuario no se relaciona
14
+ con temas jurídicos, con Justifacil y las funciones jurisdiccionales de las siguientes entidades
15
+ colombianas: SIC, DNDA, DIMAR, SNS, SFC, ICA y Supersociedades, bajo el marco
16
+ legal del Código General del Proceso (Ley 1564 de 2012). Recuerda que Justifacil es
17
+ un sistema de información que permite adelantar tramites de estas entidades, y como tal, tiene secciones de:
18
+ glosario, preguntas frecuentes, observatorio de justicia, etc.
19
+ - Siempre finaliza tu respuesta invitando al usuario a hacer más consultas.
20
+
21
+ **Instrucciones:**
22
+ - Evita tutear al usuario.
23
+ - Si la consulta del usuario no se relaciona con temas jurídicos, con Justifacil y las funciones jurisdiccionales de las siguientes entidades, inicia la respuesta con "Lo lamento, ..."
24
+ - Tu respuesta debe basarse únicamente en el 'Conocimiento' proporcionado.
25
+ - Tu respuesta debe ser amable y el lenguaje natural.
26
+ - Tu respuesta debe ser clara, concisa y relevante para la consulta del usuario.
27
+ - Evita agregar información que no esté en el 'Conocimiento'.
28
+ - Evita agregar explicaciones innecesarias o adicionales.
29
+ - Solo limitate a responder la consulta parafraseando el 'Conocimiento' proporcionado.
30
+
31
+ """
32
+
33
+ USER_PROMPT = """
34
+
35
+ Respuesta:
36
+ """
37
+
38
+ # Efectua la inferencia del modelo.
39
+ def derive(service, conocimiento, consulta, max_tkns=2000) -> any:
40
+ try:
41
+ tmp_work_memory = []
42
+ prompt = SYSTEM_PROMPT % (conocimiento, consulta)
43
+ tmp_work_memory.append({"role": "system", "content": prompt})
44
+ prompt = USER_PROMPT
45
+ tmp_work_memory.append({"role": "user", "content": prompt})
46
+ res = service.generate(tmp_work_memory, max_tokens=max_tkns)
47
+ logging.info(f"\n\n\nProcesando:\Conocimiento: {conocimiento}\nConsulta: {consulta}")
48
+ logging.info(f"Respuesta: {res}")
49
+ if not res or res == "":
50
+ res = consulta
51
+ logging.warning(f"No obtener una respuesta.")
52
+ return res
53
+ except Exception as e:
54
+ logging.error(f"Error al procesar: {consulta}")
55
+ logging.error(e)
56
+ return None
@@ -0,0 +1,58 @@
1
+ import logging
2
+
3
+ SYSTEM_PROMPT = """
4
+ [TAREA]
5
+ Eres un sistema de clasificación experto. Tu única tarea es evaluar la siguiente conversación contra las reglas proporcionadas y responder con la justificación de RECHAZO.
6
+
7
+ [DEFINICIONES]
8
+ %s
9
+
10
+ [REGLAS]
11
+ %s
12
+
13
+ [INSTRUCCIONES DE RESPUESTA]
14
+ Responde únicamente bajo las siguientes condiciones:
15
+ - Con la justificación de RECHAZO si la conversación no cumple con las reglas argumentando por qué no aplica.
16
+ - Con la justificación de RECHAZO parafrasea el concepto de reglas por el de marco normativo.
17
+ - Si la conversación cumple AL MENOS UNA de las reglas responde unicamente: SIN_COMENTARIOS.
18
+
19
+ [EJEMPLOS]
20
+ Reglas:
21
+ - Ser mayor de 18
22
+ - Vivir en México.
23
+
24
+ Texto del usuario:
25
+ - Texto: "Tengo 20 años y vivo en la Ciudad de México." -> SIN_COMENTARIOS
26
+ - Texto: "Tengo 12 y vivo en Argentina." -> RECHAZO: "No cumple con la regla de ser mayor de 18 y vivir en México."
27
+ - Texto: "Soy de México." -> SIN_COMENTARIOS
28
+
29
+ """
30
+
31
+ USER_PROMPT = """
32
+
33
+ [EVALUACIÓN ACTUAL]
34
+ Conversación:
35
+ "%s"
36
+
37
+ Respuesta:
38
+ """
39
+
40
+ # Efectua la inferencia del modelo.
41
+ def derive(service, definiciones, reglas, text, max_tkns=2000) -> any:
42
+ try:
43
+ tmp_work_memory = []
44
+ prompt = SYSTEM_PROMPT % (definiciones, reglas)
45
+ tmp_work_memory.append({"role": "system", "content": prompt})
46
+ prompt = USER_PROMPT % text
47
+ tmp_work_memory.append({"role": "user", "content": prompt})
48
+ res = service.generate(tmp_work_memory, max_tokens=max_tkns)
49
+ logging.info(f"\n\n\nProcesando:\nDefiniciones: {definiciones}\nReglas: {reglas}\nTexto: {text}")
50
+ logging.info(f"Respuesta: {res}")
51
+ if not res or res == "":
52
+ res = text
53
+ logging.warning(f"No obtener una respuesta.")
54
+ return res
55
+ except Exception as e:
56
+ logging.error(f"Error al procesar: {text}")
57
+ logging.error(e)
58
+ return None
@@ -21,7 +21,7 @@ Ejemplos:
21
21
  """
22
22
 
23
23
  # Efectua la inferencia del modelo.
24
- def derive(service, text, max_tkns=4096) -> any:
24
+ def derive(service, text, max_tkns=2000) -> any:
25
25
  try:
26
26
  logging.info(f"Procesando: {text}")
27
27
  tmp_work_memory = []
@@ -27,7 +27,8 @@ from pbesa.social.dialog import (
27
27
  DialogState, imprimir_grafo, recorrer_interacciones, extraer_diccionario_nodos,
28
28
  ActionNode, DeclarativeNode, GotoNode)
29
29
  from .celulas import (celula_casos, celula_consultas, celula_saludos, celula_datos_identificables,
30
- celula_generar_documento, celula_expertos, celula_pertinencia)
30
+ celula_generar_documento, celula_expertos, celula_pertinencia, celula_extraccion,
31
+ celula_evaluador, celula_respuesta, celula_conversador, celula_parafraseo)
31
32
  from pbesa.social.prompts import ANALIZER_PROMPT, CLASSIFICATION_PROMPT, DERIVE_PROMPT, RECOVERY_PROMPT, ADAPT_PROMPT, SINTETIZER_PROMPT
32
33
 
33
34
  # --------------------------------------------------------
@@ -544,6 +545,7 @@ class Dialog(ABC):
544
545
  self.__work_memory:list = []
545
546
  self.__meta_work_memory:list = []
546
547
  self.__system_work_memory:list = []
548
+ self.__evaluate_work_memory:list = []
547
549
  # Define role
548
550
  self.__agent_metadata = "Undefined"
549
551
  # Define role
@@ -563,6 +565,7 @@ class Dialog(ABC):
563
565
  self.__deep_limit = 9
564
566
  # Define knowledge
565
567
  self.knowledge = None
568
+ self.special_knowledge = None
566
569
  # Define point recovery
567
570
  self.__recovery = {
568
571
  "owner": "Web",
@@ -571,7 +574,7 @@ class Dialog(ABC):
571
574
  "counter": 0
572
575
  }
573
576
  # Define recovery message
574
- 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."
577
+ self.RECOVERY_MSG = "Puede darme más detalles o reformular. O si desea puede recibir asistencia humana vía correo electrónico al ministerio@minjsuticia.gov.co"
575
578
  # Define vertices list
576
579
  self.__vertices = []
577
580
  # Define visited nodes
@@ -580,6 +583,10 @@ class Dialog(ABC):
580
583
  self.__attemps = 1
581
584
  self.__analaizer_work_memory:list = []
582
585
  self.__sintetizer_work_memory:list = []
586
+ # Define production rules
587
+ self.definitions = None
588
+ self.rules = None
589
+ self.__q_attemps = 0
583
590
 
584
591
  def setup_world(self):
585
592
  """ Set up model method """
@@ -901,7 +908,7 @@ class Dialog(ABC):
901
908
  eva += 1 if es_consulta else 0
902
909
  eva += 1 if es_caso else 0
903
910
 
904
- msg = "Lo lamento, no puedo ayudarle con su consulta. Dado que no está relacionada con los servicios que presta Justifacil."
911
+ msg = "No puedo ayudarle con su consulta. Dado que no está relacionada con los servicios que presta Justifacil."
905
912
 
906
913
  # Verifica los casos
907
914
  if eva > 0 and eva < 3:
@@ -943,7 +950,7 @@ class Dialog(ABC):
943
950
 
944
951
  # Casos ambiguos con consulta y caso
945
952
  elif es_consulta and es_caso and not es_saludo:
946
- res = "Lo lamento, puede confirmar si ¿Desea que le ayude con una Consulta o una Demanda?"
953
+ res = "¿Desea que le ayude con una consulta o una demanda?"
947
954
  else:
948
955
  ambiguedad = True
949
956
  per_res = celula_pertinencia.derive(self.__ai_service, query, max_tkns=10)
@@ -1352,6 +1359,22 @@ class Dialog(ABC):
1352
1359
  else:
1353
1360
  self.notify(session['session_id'], "efectuando inferencia...")
1354
1361
  logging.info(f"[Inferencia]:[node]: {node.text}")
1362
+
1363
+ if "Evaluar: produccion-" in node.text:
1364
+ data = {"text": ""}
1365
+ for item in reversed(self.__work_memory):
1366
+ if item['role'] == 'user':
1367
+ data['text'] = item['content']
1368
+ break
1369
+ self.notify(session['session_id'], f"continuando díalogo paso a usuario")
1370
+ res = self.evaluate(session, data['text'])
1371
+ if 'Lo lamento' in res:
1372
+ logging.info(f"------------RESET---------------")
1373
+ self.reset()
1374
+ self.notify(session['session_id'], "STOP")
1375
+ return "Web", DialogState.START, res, "Web"
1376
+ return owner, node.performative, res, owner
1377
+
1355
1378
  self.__work_memory.append({"role": "system", "content": node.text})
1356
1379
  logging.info(f"=> !!!!: {query}")
1357
1380
  logging.info("-----")
@@ -1369,8 +1392,14 @@ class Dialog(ABC):
1369
1392
  # Verifica recursion
1370
1393
  if not self.chek_user_interaction(node.children):
1371
1394
  if self.__visited_nodes > 3:
1395
+ self.__visited_nodes = 0
1372
1396
  logging.info(f"[Inferencia]:[Recursion]: Deep limit")
1373
- return self.recovery(session['session_id'], "Lo lamento, no puedo responder en este momento")
1397
+ #return self.recovery(session['session_id'], "Lo lamento, no puedo responder en este momento")
1398
+ logging.info(f"------------RESET---------------")
1399
+ self.reset()
1400
+ self.notify(session['session_id'], "STOP")
1401
+ res = "Lo lamento, no puedo responder en este momento. Intentelo más tarde desde el inicio."
1402
+ return "Web", DialogState.START, res, "Web"
1374
1403
  logging.info(f"[Inferencia]:[Recursion]:[Performativa]: {node.performative}")
1375
1404
  self.notify(session['session_id'], "efectuando inferencia en profundidad")
1376
1405
  #return self.do_transition(session, owner, node, query)
@@ -1398,6 +1427,21 @@ class Dialog(ABC):
1398
1427
  :return: str
1399
1428
  """
1400
1429
  self.knowledge = knowledge
1430
+
1431
+ def set_special_knowledge(self, knowledge) -> str:
1432
+ """ Set knowledge method
1433
+ :param query: query
1434
+ :return: str
1435
+ """
1436
+ self.special_knowledge = knowledge
1437
+
1438
+ def set_production_knowledge(self, definitions, rules) -> str:
1439
+ """ Set knowledge method
1440
+ :param query: query
1441
+ :return: str
1442
+ """
1443
+ self.definitions = definitions
1444
+ self.rules = rules
1401
1445
 
1402
1446
  def adapt(self, data, profile) -> any:
1403
1447
  """ Adapt method
@@ -1439,6 +1483,95 @@ class Dialog(ABC):
1439
1483
  logging.error(e)
1440
1484
  return None
1441
1485
 
1486
+ def command_derive(self, command, query, max_tkns=2000) -> str | None:
1487
+ # data_extraction_cel
1488
+ if command == "IDENTIFICAR_VALORES":
1489
+ return celula_datos_identificables.derive(self.__ai_service, query, max_tkns=max_tkns)
1490
+ if command == "EXTRAER_DATOS":
1491
+ return celula_extraccion.derive(self.__ai_service, query, max_tkns=max_tkns)
1492
+ if command == "VERIFICAR_CONSULTA":
1493
+ return celula_consultas.derive(self.__ai_service, query, max_tkns=10)
1494
+ if command == "EVALUAR_CONSULTA":
1495
+ return celula_parafraseo.derive(self.__ai_service, self.special_knowledge, query, max_tkns=max_tkns)
1496
+ return None
1497
+
1498
+ def parse_conversation(self) -> str:
1499
+ res = ""
1500
+ if self.__evaluate_work_memory and len(self.__evaluate_work_memory) > 0:
1501
+ for item in self.__evaluate_work_memory:
1502
+ if item['role'] == 'user':
1503
+ res += f"usuario:\n{item['content']}\n"
1504
+ elif item['role'] == 'assistant':
1505
+ res += f"asistente:\n{item['content']}\n"
1506
+ else:
1507
+ logging.warning("No hay memoria de trabajo para parsear la conversación.")
1508
+ return res.strip()
1509
+
1510
+ def evaluate(self, session, query) -> str:
1511
+ try:
1512
+ self.__evaluate_work_memory.append({"role": "user", "content": query})
1513
+ # Evalua la conversación
1514
+ logging.info(f"Evaluando consulta: {query}")
1515
+ self.notify(session, "evaluando consulta...")
1516
+ for _ in range(3):
1517
+ logging.info(f"Intento de evaluación: {_+1}")
1518
+ conversacion = self.parse_conversation()
1519
+ result = celula_evaluador.derive(self.__ai_service, self.definitions, self.rules, conversacion, max_tkns=10)
1520
+ if result and not result == "":
1521
+ if "APLICA" in result:
1522
+ self.notify(session, "aplicando consulta...")
1523
+ self.__evaluate_work_memory = []
1524
+ return "Considero que el caso aplica. ¿Desea continuar con el trámite? Responda Sí o No."
1525
+ elif "RECHAZO" in result:
1526
+ self.notify(session, "rechazando consulta...")
1527
+ res_rechazo = celula_respuesta.derive(self.__ai_service, self.definitions, self.rules, conversacion, max_tkns=164)
1528
+ if res_rechazo and not res_rechazo == "":
1529
+ if "SIN_COMENTARIOS" in res_rechazo:
1530
+ continue
1531
+ self.__evaluate_work_memory = []
1532
+ return res_rechazo
1533
+ self.__evaluate_work_memory = []
1534
+ return "Considero que el caso no aplica. ¿Desea continuar con el trámite? Responda Sí o No."
1535
+ elif "PREGUNTAR" in result:
1536
+ self.__q_attemps += 1
1537
+ if self.__q_attemps > 3:
1538
+ logging.error("Se alcanzó el límite de intentos de pregunta.")
1539
+ self.__q_attemps = 0
1540
+ self.__evaluate_work_memory = []
1541
+ return "Considero que el caso no aplica. ¿Desea continuar con el trámite? Responda Sí o No."
1542
+ self.notify(session, "preguntando al usuario...")
1543
+ conversacion = self.parse_conversation()
1544
+ res = celula_conversador.derive(self.__ai_service, self.definitions, self.rules, conversacion, max_tkns=200)
1545
+ if not res and res == "":
1546
+ res = "Lo lamento, no puedo responder en este momento."
1547
+ res = res.replace("*", " ").strip()
1548
+ if 'Formulación de la pregunta' in res:
1549
+ res = res.split('Formulación de la pregunta: ')[1].strip()
1550
+ elif 'Chain of Thought' in res:
1551
+ self.__q_attemps = 0
1552
+ return "Considero que el caso no aplica. ¿Desea continuar con el trámite? Responda Sí o No."
1553
+ self.__evaluate_work_memory.append({"role": "assistant", "content": res})
1554
+ return res
1555
+ else:
1556
+ logging.warning(f"Resultado inesperado: {result}")
1557
+ self.__evaluate_work_memory = []
1558
+ return "Lo lamento, no puedo responder en este momento."
1559
+ else:
1560
+ logging.warning(f"Resultado de evaluación vacío o nulo: {result}")
1561
+ if _ < 2:
1562
+ logging.info("Reintentando evaluación...")
1563
+ continue
1564
+ else:
1565
+ self.__evaluate_work_memory = []
1566
+ logging.error("No se pudo evaluar la consulta después de 3 intentos.")
1567
+ return "Lo lamento, no puedo responder en este momento."
1568
+ self.__evaluate_work_memory = []
1569
+ return "Lo lamento, no puedo responder en este momento."
1570
+ except Exception as e:
1571
+ logging.error(f"Error al evaluar la consulta: {query}")
1572
+ logging.error(e)
1573
+ return "Lo lamento, no puedo responder en este momento."
1574
+
1442
1575
  # --------------------------------------------------------
1443
1576
  # Define Special Dispatch
1444
1577
  # --------------------------------------------------------
@@ -1507,6 +1640,7 @@ class SpecialDispatch():
1507
1640
  Response.
1508
1641
  @param data Event data
1509
1642
  """
1643
+ response = None
1510
1644
  if data and not data['dto']['session']['team'] == "Funcionalidades":
1511
1645
  logging.info("Despachando por descripcion...")
1512
1646
  options = ""
@@ -1550,7 +1684,7 @@ class SpecialDispatch():
1550
1684
  break
1551
1685
  if not select_agent:
1552
1686
  logging.info("=> No se seleccionó ningun agente")
1553
- return select_agent
1687
+ return select_agent, response
1554
1688
  else:
1555
1689
  logging.info("Despachando por descripcion...")
1556
1690
  options = ""
@@ -1654,4 +1788,4 @@ class SpecialDispatch():
1654
1788
 
1655
1789
  self.kusto_close()
1656
1790
  self.__meta_work_memory = []
1657
- return select_agent
1791
+ return select_agent, response
@@ -543,6 +543,7 @@ class LLMDispatcherDelegate(Action):
543
543
  @param data Event data
544
544
  """
545
545
  try:
546
+ response = None
546
547
  logging.info('Assign to agent...')
547
548
  session_id = data['dto']['session']['session_id'] if 'session' in data['dto'] else None
548
549
  agent_list = self.agent.get_agent_list()
@@ -580,7 +581,7 @@ class LLMDispatcherDelegate(Action):
580
581
  select_agent = self.manual_selection(data['dto'])
581
582
  # Check if agent was selected
582
583
  if not select_agent:
583
- select_agent = self.agent.special_dispatch(data)
584
+ select_agent, response = self.agent.special_dispatch(data)
584
585
  # Check if agent was selected
585
586
  if select_agent:
586
587
  logging.info(f'The agent {select_agent} will be assigned')
@@ -597,6 +598,8 @@ class LLMDispatcherDelegate(Action):
597
598
  'gateway': data['gateway'],
598
599
  'dtoList': []
599
600
  }
601
+ if response:
602
+ data['dto']['rq_query'] = response
600
603
  self.adm.send_event(ag, 'task', data['dto'])
601
604
  self.__rewier[ag] = 0
602
605
  exit = True
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pbesa
3
- Version: 4.0.28
3
+ Version: 4.0.29
4
4
  License-File: LICENSE
5
5
  License-File: LICENSE.txt
6
6
  Requires-Dist: pymongo>=4.6.3
@@ -73,11 +73,16 @@ pbesa.egg-info/top_level.txt
73
73
  pbesa/celulas/__init__.py
74
74
  pbesa/celulas/celula_casos.py
75
75
  pbesa/celulas/celula_consultas.py
76
+ pbesa/celulas/celula_conversador.py
76
77
  pbesa/celulas/celula_datos_identificables.py
78
+ pbesa/celulas/celula_evaluador.py
77
79
  pbesa/celulas/celula_expertos.py
80
+ pbesa/celulas/celula_extraccion.py
78
81
  pbesa/celulas/celula_generar_documento.py
82
+ pbesa/celulas/celula_parafraseo.py
79
83
  pbesa/celulas/celula_pertinencia.py
80
84
  pbesa/celulas/celula_preguntas.py
85
+ pbesa/celulas/celula_respuesta.py
81
86
  pbesa/celulas/celula_saludos.py
82
87
  pbesa/celulas/celula_simulador_ciudadano.py
83
88
  pbesa/celulas/data_extraction_cel.py
@@ -4,7 +4,7 @@ from setuptools import setup, find_packages
4
4
 
5
5
  setup(
6
6
  name='pbesa',
7
- version='4.0.28',
7
+ version='4.0.29',
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