Spaces:
Runtime error
Runtime error
Jorge Henao
commited on
Commit
•
44c25e2
1
Parent(s):
ae5fd49
pages refactor
Browse files- .gitignore +2 -0
- README.md +1 -1
- __pycache__/config.cpython-38.pyc +0 -0
- __pycache__/document_quieries.cpython-38.pyc +0 -0
- __pycache__/pinecode_quieries.cpython-38.pyc +0 -0
- about.py +40 -0
- app_es.py +0 -101
- app_pinecode.py +0 -165
- config.py +7 -4
- document_quieries.py +0 -60
- hallazgos.py +113 -0
- main_page.py +22 -0
- pinecode_quieries.py +84 -76
- reformas.py +131 -0
- requirements.txt +2 -2
.gitignore
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
venv/
|
2 |
+
__pycache__/
|
README.md
CHANGED
@@ -5,7 +5,7 @@ colorFrom: yellow
|
|
5 |
colorTo: blue
|
6 |
sdk: streamlit
|
7 |
sdk_version: 1.10.0
|
8 |
-
app_file:
|
9 |
pinned: True
|
10 |
license: apache-2.0
|
11 |
---
|
|
|
5 |
colorTo: blue
|
6 |
sdk: streamlit
|
7 |
sdk_version: 1.10.0
|
8 |
+
app_file: main_page.py
|
9 |
pinned: True
|
10 |
license: apache-2.0
|
11 |
---
|
__pycache__/config.cpython-38.pyc
DELETED
Binary file (569 Bytes)
|
|
__pycache__/document_quieries.cpython-38.pyc
DELETED
Binary file (3.26 kB)
|
|
__pycache__/pinecode_quieries.cpython-38.pyc
DELETED
Binary file (5.23 kB)
|
|
about.py
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
|
3 |
+
def about_ask2democracy():
|
4 |
+
st.markdown("""
|
5 |
+
<h1 style='
|
6 |
+
text-align: center;
|
7 |
+
color: #39AA35'>
|
8 |
+
Ask2Democracy 🇨🇴
|
9 |
+
</h1>
|
10 |
+
<p>Muchas de las discusiones que ocurren en Colombia generalmente están sustentadas en artículos o pdfs que salvo excpciones, casi nadie lee.
|
11 |
+
Este sistema ha indexado algunos textos relevantes para la discución pública que suelen estar dispersos y poco accesibles, además, apoyandose en modelos de lenguaje (abajo más detalles) puede entender preguntas elaboradas.
|
12 |
+
Algunos de los textos indexados: las propuestas presidenciales del 22, los hallazgos de la comisión de la verdad, los textos de las reformas, entre otros.
|
13 |
+
<div align="right">
|
14 |
+
Creado por Jorge Henao 🇨🇴 <a href="https://twitter.com/jhenaotw" target='_blank'>Twitter</a> <a href="https://www.linkedin.com/in/henaojorge" target='_blank'/>LinkedIn</a>
|
15 |
+
</div>
|
16 |
+
""", unsafe_allow_html=True)
|
17 |
+
description = """
|
18 |
+
<p>
|
19 |
+
<h2>Sobre esta iniciativa</h2>
|
20 |
+
Pretende ayudar a construir democracia participativa apaloncándose en el estado del arte de la inteligencia artificial.
|
21 |
+
Siendo una herramienta que aporta a la discución pública, empoderando al ciudadano del común para ser partícipe del debate público mientras hace preguntas en su propio lenguaje, y llegando a sus propias conclusiones.
|
22 |
+
<h2>Inteligencia artificial abierta en la democracia</h2>
|
23 |
+
Uno de los objetivos es contribuir a la inteligencia artificial abierta y en español, con la construcción de un dataset y el entrenamiento de un modelo de lenguaje adaptado para las discuciones ciudadanas.
|
24 |
+
Algo útil para elevar la calidad del debate en todos los países de habla hispana.
|
25 |
+
<h2>¿Cómo utilizar este espacio?</h2>
|
26 |
+
Selecciona el texto sobre el que quieres buscar en el panel de la izquierda. Luego puedes escribir preguntas concretas como “¿cantidad de víctimas en la masacre de bojayá?”. No se trata de un sistema de búsquedas basado en palabras clave, por el contrario, puedes redactar preguntas más extensas y elaboradas. Cuanto más contexto le des a la pregunta, mejor funciona.
|
27 |
+
<h2>Ask2Democracy v 1.2</h2>
|
28 |
+
Esta version usa sentence transformers, Cosine similarity, y una base de dactos vectorial Pinecone para mejorar la precision en las respuestas.
|
29 |
+
Los modelos transformers de lenguaje utilizados son:
|
30 |
+
<code aligh="left">
|
31 |
+
sentence-transformers/multi-qa-MiniLM-L6-cos-v1
|
32 |
+
deepset/xlm-roberta-base-squad2-distilled
|
33 |
+
</code>
|
34 |
+
<h2>Beta disclaimer</h2>
|
35 |
+
Las respuestas que arroja el sistema no han sido pregrabadas ni basadas en opiniones. Todas son respuestas extraídas de fuentes oficiales, como el Informe final de la CEV.
|
36 |
+
Este explorador usa modelos de lenguaje (sentence transformers, bert, otros ) para entender el lenguaje español, sin embargo, necesita de un mayor entrenamiento por lo que, en ocasiones, puede ser confuso y no tan preciso.
|
37 |
+
Si quieres apoyar escríbeme a <a href="mailto:jorge.henao@diezonce.co">jorge.henao@diezonce.co</a>
|
38 |
+
</p>
|
39 |
+
"""
|
40 |
+
st.markdown(description, unsafe_allow_html=True)
|
app_es.py
DELETED
@@ -1,101 +0,0 @@
|
|
1 |
-
import streamlit as st
|
2 |
-
import json
|
3 |
-
import time
|
4 |
-
from config import Config
|
5 |
-
from document_quieries import ExtractiveProposalQueries
|
6 |
-
|
7 |
-
extractive_query = ExtractiveProposalQueries(es_host = Config.es_host, es_index = Config.proposals_index,
|
8 |
-
es_user = Config.es_user, es_password = Config.es_password,
|
9 |
-
reader_name_or_path = Config.reader_model_name_or_path,
|
10 |
-
use_gpu = Config.use_gpu)
|
11 |
-
|
12 |
-
def fake_search(question, retriever_top_k, reader_top_k):
|
13 |
-
#p1_result = query.search_by_query(query = question, retriever_top_k = retriever_top_k, reader_top_k = reader_top_k, es_index = "informecomisionverdad")
|
14 |
-
result = []
|
15 |
-
p = """
|
16 |
-
La masacre de Bojayá fue perpetrada por el Frente José María Córdoba, de las FARC-EP, al lanzar un cilindro bomba que cayó en una iglesia en la que los pobladores se refugiaban del enfrentamiento de este grupo con el Bloque Élmer Cárdenas de las AUC. Las víctimas fueron 81 personas, 47 de ellas eran niñas, niños y adolescentes
|
17 |
-
"""
|
18 |
-
for i in range(0, reader_top_k):
|
19 |
-
result.append([[i+1],"81 personas", p[:250],"Las masacres","Comisión de la verdad - Informe de hallazgos y recomendaciones Junio 2022","5"])
|
20 |
-
|
21 |
-
return result
|
22 |
-
|
23 |
-
def search(question, retriever_top_k, reader_top_k):
|
24 |
-
query_result = extractive_query.search_by_query(query = question, retriever_top_k = retriever_top_k, reader_top_k = reader_top_k)
|
25 |
-
result = []
|
26 |
-
for i in range(0, len(query_result)):
|
27 |
-
item = query_result[i]
|
28 |
-
result.append([[i+1], item.answer, item.context[:200], item.meta['title'], item.meta['source'], int(item.meta['page'])])
|
29 |
-
|
30 |
-
return result
|
31 |
-
|
32 |
-
if __name__ == "__main__":
|
33 |
-
# streamlit part starts here with title
|
34 |
-
title = """
|
35 |
-
<h1 style='
|
36 |
-
text-align: center;
|
37 |
-
color: #39AA35'>
|
38 |
-
Ask2Democracy 🇨🇴 - Informe de la comisión de la verdad Junio 2022
|
39 |
-
</h1>
|
40 |
-
<p>
|
41 |
-
El 28 de junio del 2022, la Comisión de la Verdad en Colombia liberó su informe final. Fue el resultado de más de 3 años de investigación sobre el conflicto armado interno durante los últimos 60 años. Apoyándose en un modelo de inteligencia artificial. Este espacio pretende ayudar a explorar las más de 6000 páginas que conforman más de 10 libros del Informe, comenzando por el de Hallazgos y recomendaciones.
|
42 |
-
"""
|
43 |
-
st.markdown(title, unsafe_allow_html=True)
|
44 |
-
# input form
|
45 |
-
with st.form("my_form"):
|
46 |
-
# here we have input space
|
47 |
-
query = st.text_input("Ingresa la pregunta, frase abierta o tema que quieres explorar",
|
48 |
-
placeholder="Escribe tu consulta aquí...")
|
49 |
-
# Every form must have a submit button.
|
50 |
-
submitted = st.form_submit_button("Buscar")
|
51 |
-
|
52 |
-
# on submit we execute search
|
53 |
-
if(submitted):
|
54 |
-
# set start time
|
55 |
-
stt = time.time()
|
56 |
-
# retrieve top 5 documents
|
57 |
-
results = search(query, retriever_top_k=5, reader_top_k=3)
|
58 |
-
# set endtime
|
59 |
-
ent = time.time()
|
60 |
-
# measure resulting time
|
61 |
-
elapsed_time = round(ent - stt, 2)
|
62 |
-
|
63 |
-
# show which query was entered, and what was searching time
|
64 |
-
st.write(f"**Resultados relacionados con:** \"{query}\" ({elapsed_time} sec.)")
|
65 |
-
# then we use loop to show results
|
66 |
-
for i, answer in enumerate(results):
|
67 |
-
# answer starts with header
|
68 |
-
st.subheader(f"{answer[1]}")
|
69 |
-
# cropped answer
|
70 |
-
doc = answer[2][:250] + "..."
|
71 |
-
# and url to the full answer
|
72 |
-
url = f"https://www.comisiondelaverdad.co/sites/default/files/descargables/2022-06/Informe%20Final%20capi%CC%81tulo%20Hallazgos%20y%20recomendaciones.pdf#page={answer[5]+1}"
|
73 |
-
# then we display it
|
74 |
-
#st.markdown(f'{doc}\n<br>Fuente: {answer[4]}\n<br>Capítulo: {answer[3]}\n<br>Página: {answer[5]}\n[**Lee más aquí**]({url})\n', unsafe_allow_html=True)
|
75 |
-
st.markdown(f"{doc}[**Lee más aquí**]({url})")
|
76 |
-
st.caption(f"Fuente: {answer[4]} - Capítulo: {answer[3]} - Página: {answer[5]}")
|
77 |
-
|
78 |
-
st.markdown("---")
|
79 |
-
else:
|
80 |
-
st.markdown("""Cuanto más contexto le des a la pregunta, mejor funciona. puedes escribir consultas como: _**\"¿periodo con más detenciones arbitrarias registradas?\"**_,\_**\"¿cantidad de víctimas en la masacre de bojayá?\"**_,\
|
81 |
-
_**\"¿cuantas víctimas de desplazamiento en antioquia?\"**_""")
|
82 |
-
st.markdown("""
|
83 |
-
<div align="right">
|
84 |
-
Creado por Jorge Henao 🇨🇴 <a href="https://twitter.com/jhenaotw" target='_blank'>Twitter</a> <a href="https://www.linkedin.com/in/henaojorge" target='_blank'/>LinkedIn</a>
|
85 |
-
<br>Con el apoyo de Manuela Gonima en comunicaciones 🇨🇴 <a href="https://www.instagram.com/mgcomunicacionesco/" target='_blank'/>Instagram</a> <a href="https://www.linkedin.com/in/manuela-gonima-carvajal" target='_blank'/>LinkedIn</a>
|
86 |
-
</div>
|
87 |
-
""", unsafe_allow_html=True)
|
88 |
-
|
89 |
-
description = """
|
90 |
-
<p>
|
91 |
-
<h2>Sobre esta iniciativa</h2>
|
92 |
-
Se enmarca en la construcción de ciudadanía, la creación de valor público y el fortalecimiento de la democracia participativa desde la invitación a la población a informarse, conocer, compartir y dialogar en torno a la memoria histórica y a la verdad del conflicto armado colombiano, partiendo del Informe de la Comisión de la Verdad, se espera incluir varias fuentes adicionales. Hace parte de un proyecto open-source que utiliza Inteligencia Artificial para contribuir al entendimiento de temas relevantes para el país.<a href= "https://github.com/jorge-henao/ask_to_democracy"> repo en github con FastAPI</a>
|
93 |
-
</br></br>Por: Jorge Henao 🇨🇴 <a href="https://twitter.com/jhenaotw" target='_blank'>Twitter</a> <a href="https://www.linkedin.com/in/henaojorge" target='_blank'/>LinkedIn</a>, con el apoyo de Manuela Gónima 🇨🇴 <a href="https://www.instagram.com/mgcomunicacionesco/" target='_blank'/>Instagram</a> <a href="https://www.linkedin.com/in/manuela-gonima-carvajal" target='_blank'/>LinkedIn</a>
|
94 |
-
<h2>¿Cómo utilizar este espacio?</h2>
|
95 |
-
Puedes escribir oraciones abiertas como “Masacres en Antioquia”, o una pregunta concreta como “¿cantidad de víctimas en la masacre de bojayá?”. No se trata de un sistema de búsquedas basado en palabras clave, por el contrario, puedes redactar preguntas más extensas y elaboradas. Cuanto más contexto le des a la pregunta, mejor funciona.
|
96 |
-
<h2>Beta disclaimer</h2>
|
97 |
-
Las respuestas que arroja el sistema no han sido pregrabadas ni basadas en opiniones. Todas son respuestas extraídas del Informe final de la CEV, por un sistema en beta. Este explorador se basa en un modelo de inteligencia artificial entrenado para entender el lenguaje español, sin embargo, necesita de un mayor entrenamiento por lo que, en ocasiones, puede ser confuso y no tan preciso.
|
98 |
-
Si quieres apoyar escríbeme a <a href="mailto:jorge.henao@diezonce.co">jorge.henao@diezonce.co</a>
|
99 |
-
</p>
|
100 |
-
"""
|
101 |
-
st.markdown(description, unsafe_allow_html=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app_pinecode.py
DELETED
@@ -1,165 +0,0 @@
|
|
1 |
-
import streamlit as st
|
2 |
-
import json
|
3 |
-
import time
|
4 |
-
from config import Config
|
5 |
-
from pinecode_quieries import PinecodeProposalQueries
|
6 |
-
|
7 |
-
import logging
|
8 |
-
|
9 |
-
|
10 |
-
logging.basicConfig(format="%(levelname)s - %(name)s - %(message)s", level=logging.WARNING)
|
11 |
-
logging.getLogger("haystack").setLevel(logging.INFO)
|
12 |
-
|
13 |
-
logging.info("This is a test log ..")
|
14 |
-
|
15 |
-
samples_salud = """
|
16 |
-
¿Cuándo se implementará el Sistema de Salud?
|
17 |
-
¿Cómo se implementará el Sistema de Salud?
|
18 |
-
¿Qué es principio de interpretación y fundamento de la transición en relación al Sistema de Salud?
|
19 |
-
¿Qué se garantiza en todo momento con el nuevo Sistema de Salud?
|
20 |
-
¿Qué son los Centros de Atención Primaria Integrales y Resolutivos en Salud - CAPIRS?
|
21 |
-
¿Qué se garantiza durante el periodo de transición del nuevo Sistema de Salud?
|
22 |
-
¿Puede haber personas sin protección de su salud durante el periodo de transición?
|
23 |
-
¿Cuál es el derecho fundamental que se garantiza en todo momento durante la transición del nuevo Sistema de Salud?
|
24 |
-
¿En qué país se está implementando este Sistema de Salud?
|
25 |
-
¿Qué se debe realizar para garantizar la gestión de los recursos en el nivel nacional y desconcentrado?
|
26 |
-
¿Cómo se regirá el régimen de contratación de los contratos mencionados en el texto?
|
27 |
-
¿Qué son las cláusulas exorbitantes previstas en el estatuto General de Contratación de la administración pública?
|
28 |
-
¿Qué principios deben atender los contratos mencionados en el texto?
|
29 |
-
¿Cuál es el ámbito de aplicación de los contratos mencionados en el texto?
|
30 |
-
¿Quién tiene la responsabilidad de realizar la auditoría de las cuentas en relación a estos contratos?
|
31 |
-
¿Cuáles son las características que deben cumplir los contratos mencionados en el texto?
|
32 |
-
¿Qué se entiende por "coordinación" en el contexto de los contratos mencionados en el texto?
|
33 |
-
¿Qué objetivo se busca con los contratos mencionados en el texto?
|
34 |
-
¿Quién será el encargado de contratar los servicios de salud y otros requerimientos para el cumplimiento de su labor en el nivel regional?
|
35 |
-
¿Qué tipo de instituciones hospitalarias y ambulatorias se integran a la red de servicios del territorio?
|
36 |
-
¿Qué tarifas deben seguir las instituciones hospitalarias y ambulatorias para la prestación de servicios de salud?
|
37 |
-
¿Qué busca modular el régimen de tarifas y formas de pago para la prestación de servicios de salud?
|
38 |
-
¿Qué tipo de registro llevará el Fondo Regional de Salud?
|
39 |
-
¿Cuáles son algunas de las variables que se incluirán en el registro de cada servicio prestado y pagado?
|
40 |
-
"""
|
41 |
-
|
42 |
-
samples_hallazgos = """
|
43 |
-
¿Cuándo se implementará el Sistema de Salud?
|
44 |
-
¿Cómo se implementará el Sistema de Salud?
|
45 |
-
¿Qué es principio de interpretación y fundamento de la transición en relación al Sistema de Salud?
|
46 |
-
¿Qué se garantiza en todo momento con el nuevo Sistema de Salud?
|
47 |
-
¿Qué son los Centros de Atención Primaria Integrales y Resolutivos en Salud - CAPIRS?
|
48 |
-
¿Qué se garantiza durante el periodo de transición del nuevo Sistema de Salud?
|
49 |
-
¿Puede haber personas sin protección de su salud durante el periodo de transición?
|
50 |
-
¿Cuál es el derecho fundamental que se garantiza en todo momento durante la transición del nuevo Sistema de Salud?
|
51 |
-
¿En qué país se está implementando este Sistema de Salud?
|
52 |
-
¿Qué se debe realizar para garantizar la gestión de los recursos en el nivel nacional y desconcentrado?
|
53 |
-
¿Cómo se regirá el régimen de contratación de los contratos mencionados en el texto?
|
54 |
-
¿Qué son las cláusulas exorbitantes previstas en el estatuto General de Contratación de la administración pública?
|
55 |
-
¿Qué principios deben atender los contratos mencionados en el texto?
|
56 |
-
¿Cuál es el ámbito de aplicación de los contratos mencionados en el texto?
|
57 |
-
¿Quién tiene la responsabilidad de realizar la auditoría de las cuentas en relación a estos contratos?
|
58 |
-
¿Cuáles son las características que deben cumplir los contratos mencionados en el texto?
|
59 |
-
¿Qué se entiende por "coordinación" en el contexto de los contratos mencionados en el texto?
|
60 |
-
¿Qué objetivo se busca con los contratos mencionados en el texto?
|
61 |
-
¿Quién será el encargado de contratar los servicios de salud y otros requerimientos para el cumplimiento de su labor en el nivel regional?
|
62 |
-
¿Qué tipo de instituciones hospitalarias y ambulatorias se integran a la red de servicios del territorio?
|
63 |
-
¿Qué tarifas deben seguir las instituciones hospitalarias y ambulatorias para la prestación de servicios de salud?
|
64 |
-
¿Qué busca modular el régimen de tarifas y formas de pago para la prestación de servicios de salud?
|
65 |
-
¿Qué tipo de registro llevará el Fondo Regional de Salud?
|
66 |
-
¿Cuáles son algunas de las variables que se incluirán en el registro de cada servicio prestado y pagado?
|
67 |
-
"""
|
68 |
-
|
69 |
-
extractive_query = PinecodeProposalQueries (es_host = Config.es_host, es_index = Config.proposals_index,
|
70 |
-
es_user = Config.es_user, es_password = Config.es_password,
|
71 |
-
reader_name_or_path = Config.reader_model_name_or_path,
|
72 |
-
use_gpu = Config.use_gpu)
|
73 |
-
|
74 |
-
def clear_submit():
|
75 |
-
st.session_state["submit"] = False
|
76 |
-
|
77 |
-
def fake_search(question, retriever_top_k, reader_top_k):
|
78 |
-
#p1_result = query.search_by_query(query = question, retriever_top_k = retriever_top_k, reader_top_k = reader_top_k, es_index = "informecomisionverdad")
|
79 |
-
result = []
|
80 |
-
p = """
|
81 |
-
La masacre de Bojayá fue perpetrada por el Frente José María Córdoba, de las FARC-EP, al lanzar un cilindro bomba que cayó en una iglesia en la que los pobladores se refugiaban del enfrentamiento de este grupo con el Bloque Élmer Cárdenas de las AUC. Las víctimas fueron 81 personas, 47 de ellas eran niñas, niños y adolescentes
|
82 |
-
"""
|
83 |
-
for i in range(0, reader_top_k):
|
84 |
-
result.append([[i+1],"81 personas", p[:250],"Las masacres","Comisión de la verdad - Informe de hallazgos y recomendaciones Junio 2022","5"])
|
85 |
-
|
86 |
-
return result
|
87 |
-
|
88 |
-
def search(question, retriever_top_k, reader_top_k):
|
89 |
-
query_result = extractive_query.search_by_query(query = question, retriever_top_k = retriever_top_k, reader_top_k = reader_top_k)
|
90 |
-
result = []
|
91 |
-
for i in range(0, len(query_result)):
|
92 |
-
item = query_result[i]
|
93 |
-
result.append([[i+1], item.answer, item.context[:200], item.meta['title'], item.meta['source'], int(item.meta['page'])])
|
94 |
-
#result.append([[i+1], item.answer, item.context[:200], item.meta['title']])
|
95 |
-
|
96 |
-
return result
|
97 |
-
|
98 |
-
def search_and_show_results():
|
99 |
-
# set start time
|
100 |
-
stt = time.time()
|
101 |
-
# retrieve top 5 documents
|
102 |
-
results = search(query, retriever_top_k=5, reader_top_k=3)
|
103 |
-
# set endtime
|
104 |
-
ent = time.time()
|
105 |
-
# measure resulting time
|
106 |
-
elapsed_time = round(ent - stt, 2)
|
107 |
-
|
108 |
-
# show which query was entered, and what was searching time
|
109 |
-
st.write(f"**Resultados relacionados con:** \"{query}\" ({elapsed_time} sec.)")
|
110 |
-
# then we use loop to show results
|
111 |
-
for i, answer in enumerate(results):
|
112 |
-
# answer starts with header
|
113 |
-
st.subheader(f"{answer[1]}")
|
114 |
-
# cropped answer
|
115 |
-
doc = answer[2][:250] + "..."
|
116 |
-
# and url to the full answer
|
117 |
-
#url = f"https://www.comisiondelaverdad.co/sites/default/files/descargables/2022-06/Informe%20Final%20capi%CC%81tulo%20Hallazgos%20y%20recomendaciones.pdf#page={answer[5]+1}"
|
118 |
-
url = f"https://petro.presidencia.gov.co/Documents/230213-Reforma-salud.pdf"
|
119 |
-
# then we display it
|
120 |
-
#st.markdown(f'{doc}\n<br>Fuente: {answer[4]}\n<br>Capítulo: {answer[3]}\n<br>Página: {answer[5]}\n[**Lee más aquí**]({url})\n', unsafe_allow_html=True)
|
121 |
-
st.markdown(f"{doc}[**Lee más aquí**]({url})")
|
122 |
-
st.caption(f"Fuente: {answer[4]} - Capítulo: {answer[3]} - Página: {answer[5]}")
|
123 |
-
|
124 |
-
st.markdown("---")
|
125 |
-
|
126 |
-
#results = search("que es el adres", retriever_top_k=5, reader_top_k=3)
|
127 |
-
|
128 |
-
# if __name__ == "__main__":
|
129 |
-
# streamlit part starts here with title
|
130 |
-
|
131 |
-
st.set_page_config(layout="wide", page_title="Buscar")
|
132 |
-
title = """
|
133 |
-
<h1 style='
|
134 |
-
text-align: center;
|
135 |
-
color: #39AA35'>
|
136 |
-
Ask2Democracy 🇨🇴
|
137 |
-
</h1>
|
138 |
-
<p>
|
139 |
-
Muchas de las discusiones que ocurren en Colombia terminan siendo artículos o pdfs que salvo excpciones, nadie lee.
|
140 |
-
Este sistema de búsquedas usa inteligencia artificial para apoyar el entendimiendo de textos relevantes que suelen estar dispersos y poco accesibles.
|
141 |
-
Como las propuestas presidenciales del 22, los hallazgos de la comisión de la verdad, los textos de las reformas, etc.
|
142 |
-
"""
|
143 |
-
st.markdown(title, unsafe_allow_html=True)
|
144 |
-
st.markdown("""<div align="right">
|
145 |
-
Creado por Jorge Henao 🇨🇴 <a href="https://twitter.com/jhenaotw" target='_blank'>Twitter</a> <a href="https://www.linkedin.com/in/henaojorge" target='_blank'/>LinkedIn</a> </div>
|
146 |
-
""", unsafe_allow_html=True)
|
147 |
-
st.write(f"Cuanto más contexto le des a la pregunta mejor funciona el sistema.")
|
148 |
-
|
149 |
-
# Sidebar
|
150 |
-
selected_index = None
|
151 |
-
query = st.text_area("Escribe tu pregunta", on_change=clear_submit)
|
152 |
-
button = st.button("Buscar")
|
153 |
-
if button or st.session_state.get("submit"):
|
154 |
-
if not query:
|
155 |
-
st.error("¡escribe una pregunta!")
|
156 |
-
else:
|
157 |
-
st.session_state["submit"] = True
|
158 |
-
search_and_show_results()
|
159 |
-
|
160 |
-
with st.sidebar:
|
161 |
-
st.write("Ask2Democracy 🇨🇴")
|
162 |
-
selected_index = st.selectbox("Seleccion la colección sobre el que deseas buscar",
|
163 |
-
["Propuesta Reforma de la salud 2023",
|
164 |
-
"Hallazgos de la comisión de la verdad 2022"])
|
165 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
config.py
CHANGED
@@ -1,9 +1,12 @@
|
|
1 |
class Config():
|
2 |
es_host = "saimon-askwdemocracy.es.us-central1.gcp.cloud.es.io"
|
3 |
es_user = "elastic"
|
4 |
-
es_password = "53f2a7a9-ea9d-4fd2-a8bc-f471b67f0262"
|
5 |
-
|
|
|
6 |
reader_model_name_or_path = "deepset/xlm-roberta-base-squad2-distilled"
|
|
|
|
|
|
|
7 |
#reader_model_name_or_path = "deepset/xlm-roberta-base-squad2"
|
8 |
-
use_gpu = True
|
9 |
-
|
|
|
1 |
class Config():
|
2 |
es_host = "saimon-askwdemocracy.es.us-central1.gcp.cloud.es.io"
|
3 |
es_user = "elastic"
|
4 |
+
#es_password = "53f2a7a9-ea9d-4fd2-a8bc-f471b67f0262"
|
5 |
+
es_password = "1f45bf76-b600-42b3-b2cc-ab6062693eb7"
|
6 |
+
index_name = "docsreloaded"
|
7 |
reader_model_name_or_path = "deepset/xlm-roberta-base-squad2-distilled"
|
8 |
+
pinecone_environment="us-east-1-aws"
|
9 |
+
embedding_dim = 384
|
10 |
+
similarity="cosine"
|
11 |
#reader_model_name_or_path = "deepset/xlm-roberta-base-squad2"
|
12 |
+
use_gpu = True
|
|
document_quieries.py
DELETED
@@ -1,60 +0,0 @@
|
|
1 |
-
from abc import ABC, abstractmethod
|
2 |
-
from haystack.nodes import BM25Retriever, FARMReader
|
3 |
-
from haystack.document_stores import ElasticsearchDocumentStore
|
4 |
-
from haystack.pipelines import ExtractiveQAPipeline
|
5 |
-
import certifi
|
6 |
-
import datetime
|
7 |
-
import requests
|
8 |
-
from base64 import b64encode
|
9 |
-
|
10 |
-
ca_certs=certifi.where()
|
11 |
-
|
12 |
-
class DocumentQueries(ABC):
|
13 |
-
|
14 |
-
@abstractmethod
|
15 |
-
def search_by_query(self, query : str, retriever_top_k: int, reader_top_k: int, es_index: str):
|
16 |
-
pass
|
17 |
-
|
18 |
-
class ExtractiveProposalQueries(DocumentQueries):
|
19 |
-
|
20 |
-
def __init__(self, es_host: str, es_index: str, es_user, es_password, reader_name_or_path: str, use_gpu = True) -> None:
|
21 |
-
reader = FARMReader(model_name_or_path = reader_name_or_path, use_gpu = use_gpu, num_processes=1, context_window_size=200)
|
22 |
-
self._initialize_pipeline(es_host, es_index, es_user, es_password, reader = reader)
|
23 |
-
self.log = Log(es_host= es_host, es_index="log", es_user = es_user, es_password= es_password)
|
24 |
-
|
25 |
-
def _initialize_pipeline(self, es_host, es_index, es_user, es_password, reader = None):
|
26 |
-
if reader is not None:
|
27 |
-
self.reader = reader
|
28 |
-
self.es_host = es_host
|
29 |
-
self.es_user = es_user
|
30 |
-
self.es_password = es_password
|
31 |
-
self.document_store = ElasticsearchDocumentStore(host = es_host, username=es_user, password=es_password, index = es_index, port = 443, scheme='https', verify_certs=True, ca_certs=ca_certs, create_index=False)
|
32 |
-
self.retriever = BM25Retriever(document_store = self.document_store)
|
33 |
-
self.pipe = ExtractiveQAPipeline(self.reader, self.retriever)
|
34 |
-
|
35 |
-
def search_by_query(self, query : str, retriever_top_k: int, reader_top_k: int, es_index: str = None) :
|
36 |
-
self.log.write_log(query, "hfspace-informecomision")
|
37 |
-
#if es_index is not None:
|
38 |
-
#self._initialize_pipeline(self.es_host, es_index, self.es_user, self.es_password)
|
39 |
-
params = {"Retriever": {"top_k": retriever_top_k}, "Reader": {"top_k": reader_top_k}}
|
40 |
-
prediction = self.pipe.run( query = query, params = params)
|
41 |
-
return prediction["answers"]
|
42 |
-
|
43 |
-
class Log():
|
44 |
-
|
45 |
-
def __init__(self, es_host: str, es_index: str, es_user, es_password) -> None:
|
46 |
-
self.elastic_endpoint = f"https://{es_host}:443/{es_index}/_doc"
|
47 |
-
self.credentials = b64encode(b"3pvrzh9tl:4yl4vk9ijr").decode("ascii")
|
48 |
-
self.auth_header = { 'Authorization' : 'Basic %s' % self.credentials }
|
49 |
-
|
50 |
-
def write_log(self, message: str, source: str) -> None:
|
51 |
-
created_date = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%SZ')
|
52 |
-
post_data = {
|
53 |
-
"message" : message,
|
54 |
-
"createdDate": {
|
55 |
-
"date" : created_date
|
56 |
-
},
|
57 |
-
"source": source
|
58 |
-
}
|
59 |
-
r = requests.post(self.elastic_endpoint, json = post_data, headers = self.auth_header)
|
60 |
-
print(r.text)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hallazgos.py
ADDED
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from random import randint
|
2 |
+
import streamlit as st
|
3 |
+
|
4 |
+
import streamlit as st
|
5 |
+
import json
|
6 |
+
import time
|
7 |
+
from config import Config
|
8 |
+
from pinecode_quieries import PinecodeProposalQueries
|
9 |
+
import logging
|
10 |
+
logging.basicConfig(format="%(levelname)s - %(name)s - %(message)s", level=logging.WARNING)
|
11 |
+
logging.getLogger("haystack").setLevel(logging.INFO)
|
12 |
+
|
13 |
+
extractive_query = PinecodeProposalQueries (index_name= Config.index_name,
|
14 |
+
api_key = Config.es_password,
|
15 |
+
environment = Config.pinecone_environment,
|
16 |
+
embedding_dim = Config.embedding_dim,
|
17 |
+
reader_name_or_path = Config.reader_model_name_or_path,
|
18 |
+
use_gpu = Config.use_gpu)
|
19 |
+
|
20 |
+
def hallazgos_comision_verdad_2022():
|
21 |
+
title = """
|
22 |
+
<h1 style='
|
23 |
+
text-align: center;
|
24 |
+
color: #39AA35'>
|
25 |
+
Ask2Democracy 🇨🇴 - Hallazgos y recomendaciones de la comisión de la verdad
|
26 |
+
</h1>
|
27 |
+
<p>
|
28 |
+
El 28 de junio del 2022, la Comisión de la Verdad en Colombia liberó su informe final. Fue el resultado de más de 3 años de investigación sobre el conflicto armado interno durante los últimos 60 años. Apoyándose en modelos de lenguaje (sentence transformers, bert, ver más aquí). Este espacio pretende ayudar a explorar las más de 6000 páginas que conforman más de 10 libros del Informe, comenzando por el de Hallazgos y recomendaciones.
|
29 |
+
"""
|
30 |
+
st.markdown(title, unsafe_allow_html=True)
|
31 |
+
st.markdown("""<div align="right">
|
32 |
+
Creado por Jorge Henao 🇨🇴 <a href="https://twitter.com/jhenaotw" target='_blank'>Twitter</a> <a href="https://www.linkedin.com/in/henaojorge" target='_blank'/>LinkedIn</a> </div>
|
33 |
+
""", unsafe_allow_html=True)
|
34 |
+
|
35 |
+
question_samples_str = """¿cantidad de víctimas en la masacre de bojayá?
|
36 |
+
¿periodo con más detenciones arbitrarias registradas?
|
37 |
+
¿cantidad de víctimas en la masacre de bojayá?
|
38 |
+
¿cuantas víctimas de desplazamiento en antioquia?"""
|
39 |
+
|
40 |
+
question_samples = question_samples_str.splitlines()
|
41 |
+
|
42 |
+
def clear_submit():
|
43 |
+
st.session_state["submit"] = False
|
44 |
+
|
45 |
+
def fake_search(question, retriever_top_k, reader_top_k):
|
46 |
+
#p1_result = query.search_by_query(query = question, retriever_top_k = retriever_top_k, reader_top_k = reader_top_k, es_index = "informecomisionverdad")
|
47 |
+
result = []
|
48 |
+
p = """
|
49 |
+
La masacre de Bojayá fue perpetrada por el Frente José María Córdoba, de las FARC-EP, al lanzar un cilindro bomba que cayó en una iglesia en la que los pobladores se refugiaban del enfrentamiento de este grupo con el Bloque Élmer Cárdenas de las AUC. Las víctimas fueron 81 personas, 47 de ellas eran niñas, niños y adolescentes
|
50 |
+
"""
|
51 |
+
for i in range(0, reader_top_k):
|
52 |
+
result.append([[i+1],"81 personas", p[:250],"Las masacres","Comisión de la verdad - Informe de hallazgos y recomendaciones Junio 2022","5"])
|
53 |
+
|
54 |
+
return result
|
55 |
+
|
56 |
+
def search(question, retriever_top_k, reader_top_k):
|
57 |
+
filters = {"source_title": "Hallazgos y recomendaciones - 28 de Junio 2022"}
|
58 |
+
|
59 |
+
query_result = extractive_query.search_by_query(query = question,
|
60 |
+
retriever_top_k = retriever_top_k,
|
61 |
+
reader_top_k = reader_top_k,
|
62 |
+
filters = filters)
|
63 |
+
result = []
|
64 |
+
for i in range(0, len(query_result)):
|
65 |
+
item = query_result[i]
|
66 |
+
result.append([[i+1], item.answer, item.context[:200],
|
67 |
+
item.meta['title'], item.meta['source_title'], int(item.meta['page'])])
|
68 |
+
#result.append([[i+1], item.answer, item.context[:200], item.meta['title']])
|
69 |
+
return result
|
70 |
+
|
71 |
+
def search_and_show_results():
|
72 |
+
# set start time
|
73 |
+
stt = time.time()
|
74 |
+
# retrieve top 5 documents
|
75 |
+
results = search(query, retriever_top_k=5, reader_top_k=3)
|
76 |
+
# set endtime
|
77 |
+
ent = time.time()
|
78 |
+
# measure resulting time
|
79 |
+
elapsed_time = round(ent - stt, 2)
|
80 |
+
|
81 |
+
# show which query was entered, and what was searching time
|
82 |
+
st.write(f"**Resultados relacionados con:** \"{query}\" ({elapsed_time} sec.)")
|
83 |
+
# then we use loop to show results
|
84 |
+
for i, answer in enumerate(results):
|
85 |
+
# answer starts with header
|
86 |
+
st.subheader(f"{answer[1]}")
|
87 |
+
# cropped answer
|
88 |
+
doc = answer[2][:250] + "..."
|
89 |
+
# and url to the full answer
|
90 |
+
#url = f"https://www.comisiondelaverdad.co/sites/default/files/descargables/2022-06/Informe%20Final%20capi%CC%81tulo%20Hallazgos%20y%20recomendaciones.pdf#page={answer[5]+1}"
|
91 |
+
url = f"https://petro.presidencia.gov.co/Documents/230213-Reforma-salud.pdf"
|
92 |
+
# then we display it
|
93 |
+
#st.markdown(f'{doc}\n<br>Fuente: {answer[4]}\n<br>Capítulo: {answer[3]}\n<br>Página: {answer[5]}\n[**Lee más aquí**]({url})\n', unsafe_allow_html=True)
|
94 |
+
st.markdown(f"{doc}[**Lee más aquí**]({url})")
|
95 |
+
st.caption(f"Fuente: {answer[4]} - Capítulo: {answer[3]} - Página: {answer[5]}")
|
96 |
+
|
97 |
+
st.markdown("---")
|
98 |
+
|
99 |
+
#results = search("que es el adres", retriever_top_k=5, reader_top_k=3)
|
100 |
+
|
101 |
+
st.markdown(f"""<br><p>Cuanto más contexto le des a la pregunta mejor funciona el sistema.
|
102 |
+
No es un sistema basado en palabras claves, puedes escribir preguntas elaboradas.
|
103 |
+
Una serie de modelos de lenguaje transformers intervienen en cada consulta para ayudar a entenderlas.""",
|
104 |
+
unsafe_allow_html=True)
|
105 |
+
selected_question = st.selectbox("Aquí algunos ejemplos:", question_samples)
|
106 |
+
query = st.text_area("Escribe tu pregunta", value = selected_question, on_change=clear_submit)
|
107 |
+
button = st.button("Buscar")
|
108 |
+
if button or st.session_state.get("submit"):
|
109 |
+
if not query:
|
110 |
+
st.error("¡escribe una pregunta!")
|
111 |
+
else:
|
112 |
+
st.session_state["submit"] = True
|
113 |
+
search_and_show_results()
|
main_page.py
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
from about import about_ask2democracy
|
3 |
+
from hallazgos import hallazgos_comision_verdad_2022
|
4 |
+
from reformas import reforma_salud_febrero_2023
|
5 |
+
from pinecode_quieries import PinecodeProposalQueries
|
6 |
+
from config import Config
|
7 |
+
|
8 |
+
# Define the sidebar
|
9 |
+
api_key = st.sidebar.text_input("OpenAI API Key", type="password")
|
10 |
+
|
11 |
+
# Define the navigation between pages
|
12 |
+
page_options = {
|
13 |
+
"About": about_ask2democracy,
|
14 |
+
"Propuesta: Reforma a la salud febrero de 2023": reforma_salud_febrero_2023,
|
15 |
+
"Hallazgos de la comisión de la verdad 2022": hallazgos_comision_verdad_2022
|
16 |
+
}
|
17 |
+
|
18 |
+
# Define the page selector
|
19 |
+
selected_page = st.sidebar.radio("Selecciona la página que deseas explorar:", list(page_options.keys()))
|
20 |
+
|
21 |
+
# Render the selected page
|
22 |
+
page_options[selected_page]()
|
pinecode_quieries.py
CHANGED
@@ -4,7 +4,7 @@ from haystack.nodes import BM25Retriever, FARMReader
|
|
4 |
from haystack.document_stores import ElasticsearchDocumentStore
|
5 |
from haystack.pipelines import ExtractiveQAPipeline, DocumentSearchPipeline
|
6 |
from haystack.document_stores import PineconeDocumentStore
|
7 |
-
from haystack.nodes import EmbeddingRetriever
|
8 |
|
9 |
import json
|
10 |
import logging
|
@@ -17,8 +17,6 @@ from pathlib import Path
|
|
17 |
from typing import List, Optional
|
18 |
|
19 |
import pandas as pd
|
20 |
-
import pinecone
|
21 |
-
import streamlit as st
|
22 |
|
23 |
from haystack import BaseComponent, Document
|
24 |
from haystack.document_stores import PineconeDocumentStore
|
@@ -26,7 +24,10 @@ from haystack.nodes import (
|
|
26 |
EmbeddingRetriever,
|
27 |
FARMReader
|
28 |
)
|
29 |
-
from haystack.pipelines import ExtractiveQAPipeline, Pipeline
|
|
|
|
|
|
|
30 |
from sentence_transformers import SentenceTransformer
|
31 |
|
32 |
import certifi
|
@@ -34,102 +35,109 @@ import datetime
|
|
34 |
import requests
|
35 |
from base64 import b64encode
|
36 |
|
37 |
-
ca_certs=certifi.where()
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
output =
|
66 |
-
return output
|
67 |
-
|
68 |
-
def run_batch(self, queries: List[str], top_k: Optional[int]):
|
69 |
-
return {}, "output_1"
|
70 |
|
71 |
|
72 |
class DocumentQueries(ABC):
|
73 |
|
74 |
@abstractmethod
|
75 |
-
def search_by_query(self, query : str, retriever_top_k: int, reader_top_k: int,
|
76 |
pass
|
77 |
|
78 |
class PinecodeProposalQueries(DocumentQueries):
|
79 |
|
80 |
-
def __init__(self,
|
81 |
-
|
82 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
#self.log = Log(es_host= es_host, es_index="log", es_user = es_user, es_password= es_password)
|
84 |
|
85 |
-
def _initialize_pipeline(self,
|
|
|
|
|
|
|
86 |
if reader is not None:
|
87 |
self.reader = reader
|
88 |
-
|
|
|
89 |
#pinecone.init(api_key=es_password, environment="us-east1-gcp")
|
90 |
-
index_name = es_index
|
91 |
|
92 |
self.document_store = PineconeDocumentStore(
|
93 |
-
api_key=
|
94 |
-
environment =
|
95 |
-
index=index_name,
|
96 |
-
similarity=
|
97 |
-
embedding_dim=
|
98 |
-
metadata_config = {"indexed": ["title",
|
99 |
)
|
100 |
-
|
101 |
-
pinecone_retriever = PineconeRetriever("sentence-transformers/multi-qa-MiniLM-L6-cos-v1",
|
102 |
-
es_password, "us-east1-gcp",
|
103 |
-
index_name)
|
104 |
-
#self.pipe.add_node(component=pinecone_retriever, name="Retriever", inputs=["Query"])
|
105 |
-
#self.pipe.add_node(component=self.reader, name="Reader", inputs=["Retriever"])
|
106 |
-
|
107 |
-
# #self.retriever = BM25Retriever(document_store = self.document_store)
|
108 |
self.retriever = EmbeddingRetriever(
|
109 |
-
document_store=self.document_store,
|
110 |
-
#embedding_model="multi-qa-distilbert-dot-v1",
|
111 |
embedding_model = "sentence-transformers/multi-qa-MiniLM-L6-cos-v1",
|
112 |
model_format="sentence_transformers"
|
113 |
)
|
|
|
|
|
|
|
|
|
|
|
114 |
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
self.
|
121 |
-
#self.pipe = DocumentSearchPipeline(self.retriever)
|
122 |
-
|
123 |
-
def search_by_query(self, query : str, retriever_top_k: int, reader_top_k: int, es_index: str = None) :
|
124 |
-
#self.document_store.update_embeddings(self.retriever, update_existing_embeddings=False)
|
125 |
-
|
126 |
-
#if es_index is not None:
|
127 |
-
#self._initialize_pipeline(self.es_host, es_index, self.es_user, self.es_password)
|
128 |
-
params = {"Retriever": {"top_k": retriever_top_k}, "Reader": {"top_k": reader_top_k}}
|
129 |
-
#params = {"Retriever": {"top_k": retriever_top_k}}
|
130 |
-
prediction = self.pipe.run( query = query, params = params)
|
131 |
return prediction["answers"]
|
132 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
133 |
class Log():
|
134 |
|
135 |
def __init__(self, es_host: str, es_index: str, es_user, es_password) -> None:
|
|
|
4 |
from haystack.document_stores import ElasticsearchDocumentStore
|
5 |
from haystack.pipelines import ExtractiveQAPipeline, DocumentSearchPipeline
|
6 |
from haystack.document_stores import PineconeDocumentStore
|
7 |
+
from haystack.nodes import EmbeddingRetriever, OpenAIAnswerGenerator
|
8 |
|
9 |
import json
|
10 |
import logging
|
|
|
17 |
from typing import List, Optional
|
18 |
|
19 |
import pandas as pd
|
|
|
|
|
20 |
|
21 |
from haystack import BaseComponent, Document
|
22 |
from haystack.document_stores import PineconeDocumentStore
|
|
|
24 |
EmbeddingRetriever,
|
25 |
FARMReader
|
26 |
)
|
27 |
+
from haystack.pipelines import ExtractiveQAPipeline, Pipeline, GenerativeQAPipeline
|
28 |
+
from haystack.pipelines import BaseStandardPipeline
|
29 |
+
from haystack.nodes.reader import BaseReader
|
30 |
+
from haystack.nodes.retriever import BaseRetriever
|
31 |
from sentence_transformers import SentenceTransformer
|
32 |
|
33 |
import certifi
|
|
|
35 |
import requests
|
36 |
from base64 import b64encode
|
37 |
|
38 |
+
ca_certs = certifi.where()
|
39 |
+
class QAPipeline(BaseStandardPipeline):
|
40 |
+
"""
|
41 |
+
Pipeline for Extractive Question Answering.
|
42 |
+
"""
|
43 |
+
|
44 |
+
def __init__(self, reader: BaseReader, retriever: BaseRetriever):
|
45 |
+
"""
|
46 |
+
:param reader: Reader instance
|
47 |
+
:param retriever: Retriever instance
|
48 |
+
"""
|
49 |
+
self.pipeline = Pipeline()
|
50 |
+
self.pipeline.add_node(component=retriever, name="Retriever", inputs=["Query"])
|
51 |
+
self.pipeline.add_node(component=reader, name="Reader", inputs=["Retriever"])
|
52 |
+
self.metrics_filter = {"Retriever": ["recall_single_hit"]}
|
53 |
+
|
54 |
+
def run(self, query: str, params: Optional[dict] = None, debug: Optional[bool] = None):
|
55 |
+
"""
|
56 |
+
:param query: The search query string.
|
57 |
+
:param params: Params for the `retriever` and `reader`. For instance,
|
58 |
+
params={"Retriever": {"top_k": 10}, "Reader": {"top_k": 5}}
|
59 |
+
:param debug: Whether the pipeline should instruct nodes to collect debug information
|
60 |
+
about their execution. By default these include the input parameters
|
61 |
+
they received and the output they generated.
|
62 |
+
All debug information can then be found in the dict returned
|
63 |
+
by this method under the key "_debug"
|
64 |
+
"""
|
65 |
+
|
66 |
+
output = self.pipeline.run(query=query, params=params, debug=debug)
|
67 |
+
return output
|
|
|
|
|
|
|
68 |
|
69 |
|
70 |
class DocumentQueries(ABC):
|
71 |
|
72 |
@abstractmethod
|
73 |
+
def search_by_query(self, query : str, retriever_top_k: int, reader_top_k: int, index_name: str = None, filters = None):
|
74 |
pass
|
75 |
|
76 |
class PinecodeProposalQueries(DocumentQueries):
|
77 |
|
78 |
+
def __init__(self, index_name: str, api_key, reader_name_or_path: str, use_gpu = True,
|
79 |
+
embedding_dim = 384, environment = "us-east1-gcp") -> None:
|
80 |
+
|
81 |
+
reader = FARMReader(model_name_or_path = reader_name_or_path,
|
82 |
+
use_gpu = use_gpu, num_processes = 1,
|
83 |
+
context_window_size = 200)
|
84 |
+
|
85 |
+
self._initialize_pipeline(index_name, api_key, reader = reader, embedding_dim=
|
86 |
+
embedding_dim, environment = environment)
|
87 |
#self.log = Log(es_host= es_host, es_index="log", es_user = es_user, es_password= es_password)
|
88 |
|
89 |
+
def _initialize_pipeline(self, index_name, api_key, similarity = "cosine",
|
90 |
+
embedding_dim = 384, reader = None,
|
91 |
+
environment = "us-east1-gcp",
|
92 |
+
metadata_config = {"indexed": ["title", "source_title"]}):
|
93 |
if reader is not None:
|
94 |
self.reader = reader
|
95 |
+
self.OPENAI_generator = OpenAIAnswerGenerator(api_key="",
|
96 |
+
model="text-davinci-003", temperature=.5, max_tokens=60)
|
97 |
#pinecone.init(api_key=es_password, environment="us-east1-gcp")
|
|
|
98 |
|
99 |
self.document_store = PineconeDocumentStore(
|
100 |
+
api_key = api_key,
|
101 |
+
environment = environment,
|
102 |
+
index = index_name,
|
103 |
+
similarity = similarity,
|
104 |
+
embedding_dim = embedding_dim,
|
105 |
+
metadata_config = {"indexed": ["title","source_title"]}
|
106 |
)
|
107 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
108 |
self.retriever = EmbeddingRetriever(
|
109 |
+
document_store= self.document_store,
|
|
|
110 |
embedding_model = "sentence-transformers/multi-qa-MiniLM-L6-cos-v1",
|
111 |
model_format="sentence_transformers"
|
112 |
)
|
113 |
+
|
114 |
+
self.extractive_pipe = ExtractiveQAPipeline (reader = self.reader,
|
115 |
+
retriever = self.retriever)
|
116 |
+
self.generative_OPENAI_pipe = GenerativeQAPipeline(generator = self.OPENAI_generator,
|
117 |
+
retriever = self.retriever)
|
118 |
|
119 |
+
def search_by_query(self, query : str, retriever_top_k: int, reader_top_k: int, index_name: str = None, filters = None):
|
120 |
+
#self.document_store.update_embeddings(self.retriever, update_existing_embeddings=False)
|
121 |
+
params = {"Retriever": {"top_k": retriever_top_k,
|
122 |
+
"filters": filters},
|
123 |
+
"Reader": {"top_k": reader_top_k}}
|
124 |
+
prediction = self.extractive_pipe.run( query = query, params = params, debug = True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
125 |
return prediction["answers"]
|
126 |
|
127 |
+
def genenerate_answer_OpenAI(self, query : str, retriever_top_k: int, reader_top_k: int, es_index: str = None, filters = None) :
|
128 |
+
params = {"Retriever": {"top_k": retriever_top_k,
|
129 |
+
"filters": filters},
|
130 |
+
"Generator": {"top_k": reader_top_k}}
|
131 |
+
prediction = self.generative_OPENAI_pipe.run( query = query, params = params)
|
132 |
+
return prediction
|
133 |
+
|
134 |
+
def genenerate_answer_HF(self, query : str, retriever_top_k: int, reader_top_k: int, es_index: str = None, filters = None) :
|
135 |
+
params = {"Retriever": {"top_k": retriever_top_k,
|
136 |
+
"filters": filters},
|
137 |
+
"Generator": {"top_k": reader_top_k}}
|
138 |
+
prediction = self.generative_HF_pipe.run( query = query, params = params)
|
139 |
+
return prediction
|
140 |
+
|
141 |
class Log():
|
142 |
|
143 |
def __init__(self, es_host: str, es_index: str, es_user, es_password) -> None:
|
reformas.py
ADDED
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from random import randint
|
2 |
+
import streamlit as st
|
3 |
+
|
4 |
+
import streamlit as st
|
5 |
+
import json
|
6 |
+
import time
|
7 |
+
from config import Config
|
8 |
+
from pinecode_quieries import PinecodeProposalQueries
|
9 |
+
import logging
|
10 |
+
logging.basicConfig(format="%(levelname)s - %(name)s - %(message)s", level=logging.WARNING)
|
11 |
+
logging.getLogger("haystack").setLevel(logging.INFO)
|
12 |
+
|
13 |
+
extractive_query = PinecodeProposalQueries (index_name= Config.index_name,
|
14 |
+
api_key = Config.es_password,
|
15 |
+
environment = Config.pinecone_environment,
|
16 |
+
embedding_dim = Config.embedding_dim,
|
17 |
+
reader_name_or_path = Config.reader_model_name_or_path,
|
18 |
+
use_gpu = Config.use_gpu)
|
19 |
+
|
20 |
+
def reforma_salud_febrero_2023():
|
21 |
+
title = """
|
22 |
+
<h1 style='
|
23 |
+
text-align: center;
|
24 |
+
color: #39AA35'>
|
25 |
+
Ask2Democracy 🇨🇴 - Propuesta reforma a la salud 2023
|
26 |
+
</h1>
|
27 |
+
"""
|
28 |
+
st.markdown(title, unsafe_allow_html=True)
|
29 |
+
st.markdown("""<div align="right">
|
30 |
+
Creado por Jorge Henao 🇨🇴 <a href="https://twitter.com/jhenaotw" target='_blank'>Twitter</a> <a href="https://www.linkedin.com/in/henaojorge" target='_blank'/>LinkedIn</a> </div>
|
31 |
+
""", unsafe_allow_html=True)
|
32 |
+
|
33 |
+
question_samples_str = """¿Cuándo se implementará el Sistema de Salud?
|
34 |
+
¿Cómo se implementará el Sistema de Salud?
|
35 |
+
¿Qué es principio de interpretación y fundamento de la transición en relación al Sistema de Salud?
|
36 |
+
¿Qué se garantiza en todo momento con el nuevo Sistema de Salud?
|
37 |
+
¿Qué son los Centros de Atención Primaria Integrales y Resolutivos en Salud - CAPIRS?
|
38 |
+
¿Qué se garantiza durante el periodo de transición del nuevo Sistema de Salud?
|
39 |
+
¿Puede haber personas sin protección de su salud durante el periodo de transición?
|
40 |
+
¿Cuál es el derecho fundamental que se garantiza en todo momento durante la transición del nuevo Sistema de Salud?
|
41 |
+
¿En qué país se está implementando este Sistema de Salud?
|
42 |
+
¿Qué se debe realizar para garantizar la gestión de los recursos en el nivel nacional y desconcentrado?
|
43 |
+
¿Cómo se regirá el régimen de contratación de los contratos mencionados en el texto?
|
44 |
+
¿Qué son las cláusulas exorbitantes previstas en el estatuto General de Contratación de la administración pública?
|
45 |
+
¿Qué principios deben atender los contratos mencionados en el texto?
|
46 |
+
¿Cuál es el ámbito de aplicación de los contratos mencionados en el texto?
|
47 |
+
¿Quién tiene la responsabilidad de realizar la auditoría de las cuentas en relación a estos contratos?
|
48 |
+
¿Cuáles son las características que deben cumplir los contratos mencionados en el texto?
|
49 |
+
¿Qué se entiende por "coordinación" en el contexto de los contratos mencionados en el texto?
|
50 |
+
¿Qué objetivo se busca con los contratos mencionados en el texto?
|
51 |
+
¿Quién será el encargado de contratar los servicios de salud y otros requerimientos para el cumplimiento de su labor en el nivel regional?
|
52 |
+
¿Qué tipo de instituciones hospitalarias y ambulatorias se integran a la red de servicios del territorio?
|
53 |
+
¿Qué tarifas deben seguir las instituciones hospitalarias y ambulatorias para la prestación de servicios de salud?
|
54 |
+
¿Qué busca modular el régimen de tarifas y formas de pago para la prestación de servicios de salud?
|
55 |
+
¿Qué tipo de registro llevará el Fondo Regional de Salud?
|
56 |
+
¿Cuáles son algunas de las variables que se incluirán en el registro de cada servicio prestado y pagado?"""
|
57 |
+
|
58 |
+
question_samples = question_samples_str.splitlines()
|
59 |
+
|
60 |
+
def clear_submit():
|
61 |
+
st.session_state["submit"] = False
|
62 |
+
|
63 |
+
def fake_search(question, retriever_top_k, reader_top_k):
|
64 |
+
#p1_result = query.search_by_query(query = question, retriever_top_k = retriever_top_k, reader_top_k = reader_top_k, es_index = "informecomisionverdad")
|
65 |
+
result = []
|
66 |
+
p = """
|
67 |
+
La masacre de Bojayá fue perpetrada por el Frente José María Córdoba, de las FARC-EP, al lanzar un cilindro bomba que cayó en una iglesia en la que los pobladores se refugiaban del enfrentamiento de este grupo con el Bloque Élmer Cárdenas de las AUC. Las víctimas fueron 81 personas, 47 de ellas eran niñas, niños y adolescentes
|
68 |
+
"""
|
69 |
+
for i in range(0, reader_top_k):
|
70 |
+
result.append([[i+1],"81 personas", p[:250],"Las masacres","Comisión de la verdad - Informe de hallazgos y recomendaciones Junio 2022","5"])
|
71 |
+
|
72 |
+
return result
|
73 |
+
|
74 |
+
def search(question, retriever_top_k, reader_top_k):
|
75 |
+
filters = {"source_title": "Reforma de la salud 13 Febrero 2023"}
|
76 |
+
|
77 |
+
query_result = extractive_query.search_by_query(query = question,
|
78 |
+
retriever_top_k = retriever_top_k,
|
79 |
+
reader_top_k = reader_top_k,
|
80 |
+
filters = filters)
|
81 |
+
result = []
|
82 |
+
for i in range(0, len(query_result)):
|
83 |
+
item = query_result[i]
|
84 |
+
result.append([[i+1], item.answer, item.context[:200],
|
85 |
+
item.meta['title'], item.meta['source_title'], int(item.meta['page'])])
|
86 |
+
#result.append([[i+1], item.answer, item.context[:200], item.meta['title']])
|
87 |
+
return result
|
88 |
+
|
89 |
+
def search_and_show_results():
|
90 |
+
# set start time
|
91 |
+
stt = time.time()
|
92 |
+
# retrieve top 5 documents
|
93 |
+
results = search(query, retriever_top_k=5, reader_top_k=3)
|
94 |
+
# set endtime
|
95 |
+
ent = time.time()
|
96 |
+
# measure resulting time
|
97 |
+
elapsed_time = round(ent - stt, 2)
|
98 |
+
|
99 |
+
# show which query was entered, and what was searching time
|
100 |
+
st.write(f"**Resultados relacionados con:** \"{query}\" ({elapsed_time} sec.)")
|
101 |
+
# then we use loop to show results
|
102 |
+
for i, answer in enumerate(results):
|
103 |
+
# answer starts with header
|
104 |
+
st.subheader(f"{answer[1]}")
|
105 |
+
# cropped answer
|
106 |
+
doc = answer[2][:250] + "..."
|
107 |
+
# and url to the full answer
|
108 |
+
#url = f"https://www.comisiondelaverdad.co/sites/default/files/descargables/2022-06/Informe%20Final%20capi%CC%81tulo%20Hallazgos%20y%20recomendaciones.pdf#page={answer[5]+1}"
|
109 |
+
url = f"https://petro.presidencia.gov.co/Documents/230213-Reforma-salud.pdf"
|
110 |
+
# then we display it
|
111 |
+
#st.markdown(f'{doc}\n<br>Fuente: {answer[4]}\n<br>Capítulo: {answer[3]}\n<br>Página: {answer[5]}\n[**Lee más aquí**]({url})\n', unsafe_allow_html=True)
|
112 |
+
st.markdown(f"{doc}[**Lee más aquí**]({url})")
|
113 |
+
st.caption(f"Fuente: {answer[4]} - Capítulo: {answer[3]} - Página: {answer[5]}")
|
114 |
+
|
115 |
+
st.markdown("---")
|
116 |
+
|
117 |
+
#results = search("que es el adres", retriever_top_k=5, reader_top_k=3)
|
118 |
+
|
119 |
+
st.write(f"""<br><p>Cuanto más contexto le des a la pregunta mejores resultados se obtienen.
|
120 |
+
No es un sistema basado en palabras claves, puedes escribir preguntas elaboradas.
|
121 |
+
Una serie de modelos de lenguaje transformers intervienen en cada consulta para ayudar a entenderlas."""
|
122 |
+
,unsafe_allow_html=True)
|
123 |
+
selected_question = st.selectbox("Aquí algunos ejemplos:", question_samples)
|
124 |
+
query = st.text_area("Escribe tu pregunta", value = selected_question, on_change=clear_submit)
|
125 |
+
button = st.button("Buscar")
|
126 |
+
if button or st.session_state.get("submit"):
|
127 |
+
if not query:
|
128 |
+
st.error("¡escribe una pregunta!")
|
129 |
+
else:
|
130 |
+
st.session_state["submit"] = True
|
131 |
+
search_and_show_results()
|
requirements.txt
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
streamlit==1.15.0
|
2 |
sentence-transformers
|
3 |
farm-haystack[pinecone]
|
4 |
-
pinecone-client
|
|
|
|
|
|
1 |
sentence-transformers
|
2 |
farm-haystack[pinecone]
|
3 |
+
pinecone-client
|
4 |
+
streamlit==1.15.0
|