Spaces:
Sleeping
Sleeping
import gradio as gr | |
from modules.extractive import TFIDFSummarizer, TextRankSummarizer, CombinedSummarizer, BERTSummarizer | |
from modules.abstractive import load_summarizers, abstractive_summary | |
from modules.preprocessing import Preprocessor, PDFProcessor | |
from modules.utils import handle_long_text | |
# Cargar modelos abstractivos finetuneados | |
summarizers = load_summarizers() | |
# Ejemplo de texto | |
EXAMPLE_TEXT = """ | |
La inteligencia artificial (IA) ha revolucionado múltiples industrias, desde la medicina hasta el transporte. | |
Los avances en modelos de lenguaje, como T5, BART y PEGASUS, permiten aplicaciones innovadoras como la generación automática de resúmenes, lo cual facilita el acceso a información clave en documentos extensos. | |
""" | |
# Función para procesar el archivo cargado | |
def process_file(file): | |
""" | |
Procesa un archivo cargado y extrae texto si es un PDF válido. | |
Args: | |
file (UploadedFile): Archivo subido por el usuario. | |
Returns: | |
str: Texto extraído del archivo o mensaje de error. | |
""" | |
if file is not None: | |
pdf_processor = PDFProcessor() | |
input_text = pdf_processor.pdf_to_text(file.name) | |
if input_text.strip(): | |
return input_text | |
return "El archivo no contiene texto procesable." | |
return "Por favor, cargue un archivo válido." | |
# Función para cargar un ejemplo de texto | |
def load_example_text(): | |
""" | |
Devuelve un ejemplo de texto predefinido. | |
Returns: | |
str: Texto de ejemplo. | |
""" | |
return EXAMPLE_TEXT | |
# Función para cargar y limpiar el contenido de un archivo | |
def process_uploaded_file(file): | |
""" | |
Procesa un archivo, lo limpia y devuelve su contenido en texto. | |
Args: | |
file (UploadedFile): Archivo subido. | |
Returns: | |
str: Texto limpio extraído del archivo. | |
""" | |
raw_text = process_file(file) | |
if "El archivo no contiene" not in raw_text and "Por favor" not in raw_text: | |
preprocessor = Preprocessor() | |
return preprocessor.clean_text(raw_text) | |
return raw_text | |
# | |
def summarize(input_text, file, summary_type, method, num_sentences, model_name, max_length, num_beams): | |
""" | |
Genera un resumen basado en el texto de entrada o archivo cargado. | |
Args: | |
input_text (str): Texto ingresado por el usuario. | |
file (UploadedFile): Archivo subido por el usuario. | |
summary_type (str): Tipo de resumen: Extractivo, Abstractivo o Combinado. | |
method (str): Método de resumen extractivo. | |
num_sentences (int): Número de oraciones para el resumen extractivo. | |
model_name (str): Nombre del modelo para resumen abstractivo. | |
max_length (int): Longitud máxima del resumen generado. | |
num_beams (int): Número de haces para búsqueda en el modelo. | |
Returns: | |
str: Resumen generado o mensaje de error. | |
""" | |
preprocessor = Preprocessor() | |
# Procesar archivo si se sube uno | |
if file is not None: | |
input_text = process_file(file) | |
# Validar que haya texto para resumir | |
if not input_text.strip(): | |
return "Por favor, ingrese texto o cargue un archivo válido." | |
cleaned_text = preprocessor.clean_text(input_text) | |
# Procesar según el tipo de resumen seleccionado | |
if summary_type == "Extractivo": | |
if method == "TF-IDF": | |
summarizer = TFIDFSummarizer() | |
elif method == "TextRank": | |
summarizer = TextRankSummarizer() | |
elif method == "BERT": | |
summarizer = BERTSummarizer() | |
elif method == "TF-IDF + TextRank": | |
summarizer = CombinedSummarizer() | |
else: | |
return "Método no válido para resumen extractivo." | |
return summarizer.summarize( | |
preprocessor.split_into_sentences(cleaned_text), | |
preprocessor.clean_sentences(preprocessor.split_into_sentences(cleaned_text)), | |
num_sentences, | |
) | |
elif summary_type == "Abstractivo": | |
if model_name not in summarizers: | |
return "Modelo no disponible para resumen abstractivo." | |
return handle_long_text( | |
cleaned_text, | |
summarizers[model_name][0], | |
summarizers[model_name][1], | |
max_length=max_length, | |
stride=128, | |
) | |
elif summary_type == "Combinado": | |
if model_name not in summarizers: | |
return "Modelo no disponible para resumen abstractivo." | |
extractive_summary = TFIDFSummarizer().summarize( | |
preprocessor.split_into_sentences(cleaned_text), | |
preprocessor.clean_sentences(preprocessor.split_into_sentences(cleaned_text)), | |
num_sentences, | |
) | |
return handle_long_text( | |
extractive_summary, | |
summarizers[model_name][0], | |
summarizers[model_name][1], | |
max_length=max_length, | |
stride=128, | |
) | |
return "Seleccione un tipo de resumen válido." | |
# Interfaz dinámica | |
with gr.Blocks() as interface: | |
gr.Markdown("# Aplicación Híbrida para Resumir Documentos de Forma Extractiva y Abstractiva") | |
# Entrada de texto o archivo | |
with gr.Row(): | |
with gr.Column(scale=2): | |
input_text = gr.Textbox(lines=9, label="Ingrese texto", interactive=True) | |
with gr.Row(): | |
load_example_button = gr.Button("Load Example") | |
upload_file_button = gr.Button("Upload File") | |
with gr.Column(scale=1): | |
file = gr.File(label="Subir archivo (PDF, TXT)") | |
# Acciones de botones | |
load_example_button.click( | |
load_example_text, | |
inputs=[], | |
outputs=[input_text], | |
) | |
upload_file_button.click( | |
process_uploaded_file, | |
inputs=[file], | |
outputs=[input_text], | |
) | |
# Selección de tipo de resumen y opciones dinámicas | |
summary_type = gr.Radio( | |
["Extractivo", "Abstractivo", "Combinado"], | |
label="Tipo de resumen", | |
value="Extractivo", | |
) | |
method = gr.Radio( | |
["TF-IDF", "TextRank", "BERT", "TF-IDF + TextRank"], | |
label="Método Extractivo", | |
visible=True, | |
) | |
num_sentences = gr.Slider( | |
1, 10, value=3, step=1, label="Número de oraciones (Extractivo)", visible=True | |
) | |
model_name = gr.Radio( | |
["Pegasus", "T5", "BART"], | |
label="Modelo Abstractivo", | |
visible=False, | |
) | |
max_length = gr.Slider( | |
50, 300, value=128, step=10, label="Longitud máxima (Abstractivo)", visible=False | |
) | |
num_beams = gr.Slider( | |
1, 10, value=4, step=1, label="Número de haces (Abstractivo)", visible=False | |
) | |
def update_options(summary_type): | |
if summary_type == "Extractivo": | |
return ( | |
gr.update(visible=True), gr.update(visible=True), gr.update(visible=False), gr.update(visible=False), | |
gr.update(visible=False)) | |
elif summary_type == "Abstractivo": | |
return ( | |
gr.update(visible=False), gr.update(visible=False), gr.update(visible=True), gr.update(visible=True), | |
gr.update(visible=True)) | |
elif summary_type == "Combinado": | |
return (gr.update(visible=True), gr.update(visible=True), gr.update(visible=True), gr.update(visible=True), | |
gr.update(visible=True)) | |
else: | |
return ( | |
gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), | |
gr.update(visible=False)) | |
summary_type.change( | |
update_options, | |
inputs=[summary_type], | |
outputs=[method, num_sentences, model_name, max_length, num_beams], | |
) | |
summarize_button = gr.Button("Generar Resumen") | |
output = gr.Textbox(lines=10, label="Resumen generado", interactive=True) | |
copy_button = gr.Button("Copiar Resumen") | |
summarize_button.click( | |
summarize, | |
inputs=[input_text, file, summary_type, method, num_sentences, model_name, max_length, num_beams], | |
outputs=output, | |
) | |
def copy_summary(summary): | |
return summary | |
copy_button.click( | |
fn=copy_summary, | |
inputs=[output], | |
outputs=[output], | |
js="""function(summary) { navigator.clipboard.writeText(summary); return summary; }""", | |
) | |
if __name__ == "__main__": | |
interface.launch() | |