File size: 11,162 Bytes
64dce50
c188624
 
538f893
cd22fcf
c188624
108d27a
c188624
 
3285b2f
d93b1a1
3cb588d
89d461c
165da8a
f9aee31
d93b1a1
2223cef
2dc3466
 
b6bf0ba
2223cef
 
32c554f
 
 
 
 
 
 
 
 
4f11d9a
 
6e6a875
1c6da43
d51f1cc
 
19e8047
d51f1cc
1221fe9
32c554f
 
 
c188624
 
c8e2bd5
1d8cafe
633e74c
3a6124d
c188624
 
 
 
88bce4f
4d25120
f0d04b2
8ca54ac
1243889
8ca54ac
88bce4f
cdb1a5c
 
f15985e
cdb1a5c
 
e3c12c6
f15985e
83f59d1
 
a17b65d
4d25120
 
a17b65d
d85140a
a17b65d
a4616f8
a17b65d
615de2a
a17b65d
c90738f
a17b65d
 
1d8cafe
 
 
 
 
 
 
a9dedd2
a17b65d
 
882904a
83f59d1
 
d85140a
a17b65d
5421eee
ba4a859
5421eee
4a0bcf5
5421eee
5d8ce62
 
5421eee
a17b65d
 
e85f2a8
37f8221
a081285
f4f4fc9
3e1af0d
 
c188624
 
3a6124d
108d27a
c188624
 
43d259e
c188624
 
842daf1
 
f3e7009
4e396fc
c530fdd
8652040
842daf1
e9627f7
c188624
 
4d25120
 
77cd9f6
c188624
d56623b
8931e64
 
9410935
8931e64
50aa783
 
 
9410935
f0e3cd1
 
291af26
 
f0e3cd1
67e6484
6558791
0bd89a6
3f3ff1b
0bd89a6
bc75b5c
6558791
bc75b5c
 
 
f17ab7b
 
 
bc75b5c
 
 
7a54e8d
8116f72
f0e3cd1
4d25120
 
 
 
 
5579ffd
4d25120
8116f72
ad5ccf6
39e0e59
ad5ccf6
36b1894
ad5ccf6
 
 
 
 
 
 
5579ffd
8931e64
 
 
 
 
 
f028df8
0b42aa0
750fb1c
 
0b42aa0
750fb1c
 
 
f028df8
750fb1c
 
 
f028df8
750fb1c
 
 
 
0b42aa0
8931e64
d56623b
b3ca400
 
c188624
 
 
 
 
 
 
 
 
0bb7e36
c188624
963ec7c
6803992
b518608
bd37214
 
 
 
57bca4c
5997e16
e6f4a11
75dfc30
2819576
75dfc30
 
 
 
 
 
 
 
 
 
 
 
 
 
94e535e
ad40ecb
b518608
2223cef
1464ea3
2983fa6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
import numpy as np
import pandas as pd
import streamlit as st
import streamlit.components.v1 as components
from transformers import *
from carga_articulos import cargar_articulos
from preprocesamiento_articulos import limpieza_articulos, remove_URL, remove_html_markup, remove_emoji, remover_casos_especiales, frases_remover, obtener_kpes
from entrenamiento_modelo import term_document_matrix, tf_idf_score
from resultados_consulta import resultados_consulta, detalles_resultados
import tensorflow as tf
import tensorflow.python.ops.numpy_ops.np_config as np_config
from math import ceil
from datetime import datetime

##

def split_frame(input_df, rows):
    df=[]
    for i in range(0, len(input_df), rows):
        df.append(input_df.iloc[i : i + rows, :])
    return df

def paginar_frame(df):
     N_cards_per_row = 1
     for n_row, row in df.reset_index().iterrows():
        i = n_row%N_cards_per_row
        if i==0:
            st.write("---")
            cols = st.columns(N_cards_per_row, gap="large")
        # draw the card
        with cols[n_row%N_cards_per_row]:
            if 'answer' in row:
                if (row['answer']):
                    t= row['answer'] + ' (score: ' + str(row['score']) + ')'
                    st.info(t)
            row['resumen']=remove_html_markup(row['resumen'])
            row['resumen']=remove_URL(row['resumen'])
            if (len(row['resumen'])>600):
                row['resumen']=row['resumen'][0:600]     
            st.caption(f"{row['feed'].strip()} - {row['seccion'].strip()} - {row['fecha'].strip()} ")
            st.markdown(f"**{row['titulo'].strip()}**")
            st.markdown(f"{row['resumen'].strip()}")
            st.markdown(f"{row['link']}")

def load_qa_model():

    tokenizer = AutoTokenizer.from_pretrained('dccuchile/bert-base-spanish-wwm-uncased', use_fast="false")
    model = TFAutoModelForQuestionAnswering.from_pretrained("Lisibonny/modelo_qa_beto_squad_es_pdqa")
    return tokenizer, model

# 4. Use streamlit to create a web app
def main():

    
    
    st.set_page_config(page_title="Buscador de noticias periodicos dominicanos", page_icon="📰", layout="centered")
    st.image('repartidor_periodicos.jpeg', width=150)
    st.header('El Repartidor Dominicano :red[experimental]')

    df, fecha_min, fecha_max=cargar_articulos()
    fecha_min=fecha_min[:19]
    fecha_max=fecha_max[:19]

    fecha_min=datetime.strptime(fecha_min, '%Y-%m-%d %H:%M:%S')
    fecha_max=datetime.strptime(fecha_max, '%Y-%m-%d %H:%M:%S')
    
    days=(fecha_max-fecha_min).days
    fecha_min=fecha_min.strftime("%d-%m-%Y %I:%M %p")
    fecha_max=fecha_max.strftime("%d-%m-%Y %I:%M %p")
    
    usar_barra_progreso=1 
    
    # Sidebar
    st.sidebar.header("Acerca De")
    st.sidebar.markdown(
        "El Repartidor Dominicano es un sistema de recuperación de información desde periódicos dominicanos que usa técnicas de aprendizaje automático."
    )
    st.sidebar.markdown("Desarrollado por [Lisibonny Beato-Castro](https://scholar.google.com/citations?user=KSzjfeUAAAAJ&hl=es&oi=ao)")
    
    st.sidebar.header("Artículos Indexados")
    st.sidebar.markdown(
        """
    Fuentes: 

     - [Diario Libre](https://www.diariolibre.com/)
     - [El Nacional](https://www.elnacional.com.do/)
     - [Remolacha.net](https://www.remolacha.net/)
     - [AlMomento.net](https://almomento.net/)
     - [Gente Tuya](http://www.gentetuya.com)
    
    """
    )
    st.sidebar.markdown(f"Noticias de los últimos: **{days} días**")
    st.sidebar.markdown(f"Fecha más antigua: **{fecha_min}**")
    st.sidebar.markdown(f"Fecha más reciente: **{fecha_max}**")
    st.sidebar.header("Aviso Legal Sobre Uso de Datos")
    st.sidebar.markdown(
        """
        El uso de los artículos en este sitio tiene fines no comerciales, respetando los derechos de autor. Implementamos las mejores prácticas para el uso de RSS, tal y como son recomendadas por el Berkman Klein Center for Internet & Society de la Universidad de Harvard.
        
        Si quieres saber más acerca de los feeds RSS o de las mejores prácticas para el uso de RSS, haz clic en los siguientes enlaces:
        
        - [RSS](https://es.wikipedia.org/wiki/RSS)
        - [Uso legal de feeds RSS](https://cyber.harvard.edu/publications/2010/news_aggregator_legal_implications_best_practices)
        """
    )

    st.sidebar.header("¡Cómprame un Café!")
    st.sidebar.markdown("Si te gusta este sitio y quieres darme las gracias o animarme a hacer más, puedes hacer una pequeña donación.")
    with st.sidebar:
        st.markdown("[![Haz clic aquí](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/donate/?hosted_button_id=VK5ZAB52ZYDNA)")


    articulos_indexados = pd.read_csv('articulos_indexados.csv')
    articulos_indexados = articulos_indexados.set_index('Unnamed: 0')
    tokenizer, qa_model = load_qa_model()
    kpes=obtener_kpes(df)

    query = st.text_input(
        "Escribe tus términos de búsqueda o haz una pregunta usando los caracteres ¿?:"
    )

    # Topicos populares
    st.write("Tópicos populares en los artículos indexados:")
    cadena  = ':blue['
    for value in kpes:
        cadena = cadena + ' - ' + str(value[0])
    cadena=cadena + ']'    
    st.write(cadena)
    
    if query:

        # Si se especifico una pregunta
        
        if (('¿' == query[0]) and ('?' == query[len(query)-1])):
           st.write("Contestando a: ", query)
           # Verificando cada resumen de los articulos como contexto a la pregunta 
           cantidad_respuestas = 0 
           lista_noticias_respuestas = [] 
           all_results = pd.DataFrame(columns=["id","answer","score","start","end"])
           df_answer=df
           df_answer['answer']=''
           df_answer['score'] =0
            
            
           progress_text = "Buscando respuestas. Por favor, espere."
           my_bar = st.progress(0, text=progress_text)
           total_respuestas = len(df_answer)
           for i in range(total_respuestas):
                     
               text=remove_html_markup(df_answer.loc[i, "resumen"])
               text=remove_URL(text)
               text=remove_emoji(text)
               text=frases_remover(text)
               text=remover_casos_especiales(text)
               
               inputs =  tokenizer(query, text[0:512], return_tensors='tf')
               input_ids = inputs["input_ids"].numpy()[0]

               text_tokens = tokenizer.convert_ids_to_tokens(input_ids)
               outputs = qa_model(inputs)
               answer_start = tf.argmax(outputs.start_logits, axis=1).numpy()[0]
               answer_end = (tf.argmax(outputs.end_logits, axis=1) + 1).numpy()[0] 
                
               answer = tokenizer.convert_tokens_to_string(tokenizer.convert_ids_to_tokens(input_ids[answer_start:answer_end]))

               all_results.loc[i] = i,answer, max(outputs.start_logits.numpy()[0]), 0, 0
                           
               # Barra de progreso
               if (usar_barra_progreso==1):
                   porcentaje_progreso = round((i/total_respuestas)*100)
                   if (porcentaje_progreso in range (1,101)):
                       my_bar.progress(porcentaje_progreso, text=progress_text)
           
           my_bar.empty()
           usar_barra_progreso = 0

           # Obteniendo las respuestas con los 10 scores mas altos
           all_results=all_results.sort_values(by=['score'], ascending=False).head(5)
           # Si hay alguna de ellas que diga que no hay respuesta, no se traera ninguna 
           if not (all_results['answer'].isnull().any()):
               for index, row in all_results.iterrows():
                   if (len(row['answer'])>0):    
                       cantidad_respuestas = cantidad_respuestas + 1
                       i=row['id']
                       df_answer.loc[i, "answer"] = row.loc['answer']
                       df_answer.loc[i, "score"]= row.loc['score']
                       lista_noticias_respuestas.append(df_answer.loc[i].to_frame().T)
            
           df_noticias_respuestas=pd.concat(lista_noticias_respuestas)
           batch_size = 5
           pages = split_frame(df_noticias_respuestas, batch_size)
           top_menu = st.columns(3)
                
           pagination = st.container()
            
           bottom_menu = st.columns((3))

           with pagination: 
            
               with bottom_menu[2]:
                   total_pages = (ceil(cantidad_respuestas / batch_size) if ceil(cantidad_respuestas / batch_size) > 0 else 1)
                   current_page = st.number_input("Página", min_value=1, max_value=total_pages, step=1)  
                    
               with bottom_menu[1]:
                   st.write("---")
                   st.markdown(f"Página **{current_page}** de **{total_pages}** ") 
                    
               with top_menu[0]:
                   pagina_res_fin= batch_size*current_page if batch_size*current_page <= cantidad_respuestas else cantidad_respuestas
                   st.markdown(f"Respuestas **{(current_page*batch_size)-batch_size+1}-{pagina_res_fin}**  de  **{cantidad_respuestas}** ") 
                        
               paginar_frame(pages[current_page - 1]) 
                  
                   

        # Si se especificaron keywords
        else:    

            st.write("Buscando: ", query)
            result = resultados_consulta(df,articulos_indexados, query)

            if result.empty:
                st.info("No se encontraron artículos para la búsqueda solicitada")

            else:
            
                df_results=detalles_resultados(df,result)
                cantidad_resultados=len(df_results)
                batch_size = 5
                pages = split_frame(df_results, batch_size)
                top_menu = st.columns(3)
                    
                pagination = st.container()
                
                
                bottom_menu = st.columns((3))
            
                
                    
                with bottom_menu[2]:
                    total_pages = (ceil(cantidad_resultados / batch_size) if ceil(cantidad_resultados / batch_size) > 0 else 1)
                    current_page = st.number_input("Página", min_value=1, max_value=total_pages, step=1)  
                    
                with bottom_menu[1]:
                    st.write("---")
                    st.markdown(f"Página **{current_page}** de **{total_pages}** ") 
                    
                with top_menu[0]:
                    pagina_res_fin= batch_size*current_page if batch_size*current_page <= cantidad_resultados else cantidad_resultados
                    st.markdown(f"Artículos **{(current_page*batch_size)-batch_size+1}-{pagina_res_fin}**  de  **{cantidad_resultados}** ") 
                
                with pagination:        
                
                    paginar_frame(pages[current_page - 1])
                
                
                        
if __name__ == "__main__": 
    main()