|
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") |
|
|
|
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 |
|
|
|
|
|
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 |
|
|
|
|
|
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 ¿?:" |
|
) |
|
|
|
|
|
st.write("Tópicos populares en los artículos indexados:") |
|
cadena = '' |
|
for value in kpes: |
|
cadena = cadena + ' - ' + str(value[0]) |
|
st.write(cadena) |
|
|
|
if query: |
|
|
|
|
|
|
|
if (('¿' == query[0]) and ('?' == query[len(query)-1])): |
|
st.write("Contestando a: ", query) |
|
|
|
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 |
|
|
|
|
|
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 |
|
|
|
|
|
all_results=all_results.sort_values(by=['score'], ascending=False).head(5) |
|
|
|
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]) |
|
|
|
|
|
|
|
|
|
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() |