import os import requests import gradio as gr from download_url import download_text_and_title from cache_system import CacheHandler from collections import OrderedDict from typing import Any, Iterable, List import datetime import json server = os.environ.get("SERVER") or "http://localhost:7861/generate" auth_token = os.environ.get("TOKEN") or True API_KEY = os.environ.get("API_KEY") or None total_runs = 0 def call_vllm_server(tittle, body, mode, stream=True): api_url = server headers = {"User-Agent": "Test Client"} json = { "n": 1, "tittle": tittle, "body": body, "mode": mode, "max_tokens": 4096, "temperature": 0.15, "top_p": 0.1, "top_k": 40, "repetition_penalty": 1.1, "stop": [ "", "", "\\n", "<|im_end|>", ], "stream": stream, "api_key": API_KEY, } response = requests.post(api_url, headers=headers, json=json) return response def get_streaming_response(response: requests.Response) -> Iterable[List[str]]: for chunk in response.iter_lines( chunk_size=8192, decode_unicode=False, delimiter=b"\0" ): if chunk: data = json.loads(chunk.decode("utf-8")) output = data["text"] yield output class HuggingFaceDatasetSaver_custom(gr.HuggingFaceDatasetSaver): def _deserialize_components( self, data_dir, flag_data: list[Any], flag_option: str = "", username: str = "", ) -> tuple[dict[Any, Any], list[Any]]: """Deserialize components and return the corresponding row for the flagged sample. Images/audio are saved to disk as individual files. """ # Components that can have a preview on dataset repos file_preview_types = {gr.Audio: "Audio", gr.Image: "Image"} # Generate the row corresponding to the flagged sample features = OrderedDict() row = [] for component, sample in zip(self.components, flag_data): label = component.label or "" features[label] = {"dtype": "string", "_type": "Value"} row.append(sample) features["flag"] = {"dtype": "string", "_type": "Value"} features["username"] = {"dtype": "string", "_type": "Value"} row.append(flag_option) row.append(username) return features, row def finish_generation(text: str) -> str: return f"{text}\n\n⬇️ Ayuda a mejorar la herramienta marcando si el resumen es correcto o no.⬇️" def generate_text( url: str, mode: int, progress=gr.Progress(track_tqdm=False) ) -> (str, str): global cache_handler global total_runs total_runs += 1 print(f"Total runs: {total_runs}. Last run: {datetime.datetime.now()}") url = url.strip() if url.startswith("https://twitter.com/") or url.startswith("https://x.com/"): yield ( "🤖 Vaya, parece que has introducido la url de un tweet. No puedo acceder a tweets, tienes que introducir la URL de una noticia.", "❌❌❌ Si el tweet contiene una noticia, dame la URL de la noticia ❌❌❌", "Error", ) return ( "🤖 Vaya, parece que has introducido la url de un tweet. No puedo acceder a tweets, tienes que introducir la URL de una noticia.", "❌❌❌ Si el tweet contiene una noticia, dame la URL de la noticia ❌❌❌", "Error", ) # 1) Download the article progress(0, desc="🤖 Accediendo a la noticia") # First, check if the URL is in the cache title, text, temp = cache_handler.get_from_cache(url, mode) if title is not None and text is not None and temp is not None: temp = finish_generation(temp) yield title, temp, text return title, temp, text else: try: title, text, url = download_text_and_title(url) except Exception as e: print(e) title = None text = None if title is None or text is None: yield ( "🤖 No he podido acceder a la notica, asegurate que la URL es correcta y que es posible acceder a la noticia desde un navegador.", "❌❌❌ Inténtalo de nuevo ❌❌❌", "Error", ) return ( "🤖 No he podido acceder a la notica, asegurate que la URL es correcta y que es posible acceder a la noticia desde un navegador.", "❌❌❌ Inténtalo de nuevo ❌❌❌", "Error", ) # Test if the redirected and clean url is in the cache _, _, temp = cache_handler.get_from_cache(url, mode, second_try=True) if temp is not None: temp = finish_generation(temp) yield title, temp, text return title, temp, text progress(0.5, desc="🤖 Leyendo noticia") try: response = call_vllm_server(title, text, mode, stream=True) for h in get_streaming_response(response): temp = h[0] yield title, temp, text except Exception as e: print(e) yield ( "🤖 El servidor no se encuentra disponible.", "❌❌❌ Inténtalo de nuevo más tarde ❌❌❌", "Error", ) return ( "🤖 El servidor no se encuentra disponible.", "❌❌❌ Inténtalo de nuevo más tarde ❌❌❌", "Error", ) cache_handler.add_to_cache( url=url, title=title, text=text, summary_type=mode, summary=temp ) temp = finish_generation(temp) yield title, temp, text hits, misses, cache_len = cache_handler.get_cache_stats() print( f"Hits: {hits}, misses: {misses}, cache length: {cache_len}. Percent hits: {round(hits/(hits+misses)*100,2)}%." ) return title, temp, text cache_handler = CacheHandler(max_cache_size=1000) hf_writer = HuggingFaceDatasetSaver_custom( auth_token, "Iker/Clickbait-News", private=True, separate_dirs=False ) demo = gr.Interface( generate_text, inputs=[ gr.Textbox( label="🌐 URL de la noticia", info="Introduce la URL de la noticia que deseas resumir.", value="https://ikergarcia1996.github.io/Iker-Garcia-Ferrero/", interactive=True, ), gr.Slider( minimum=0, maximum=100, step=50, value=50, label="🎚️ Nivel de resumen", info="""¿Hasta qué punto quieres resumir la noticia? Si solo deseas un resumen, selecciona 0. Si buscas un resumen y desmontar el clickbait, elige 50. Para obtener solo la respuesta al clickbait, selecciona 100""", interactive=True, ), ], outputs=[ gr.Textbox( label="📰 Titular de la noticia", interactive=False, placeholder="Aquí aparecerá el título de la noticia", ), gr.Textbox( label="🗒️ Resumen", interactive=False, placeholder="Aquí aparecerá el resumen de la noticia.", ), gr.Textbox( label="Noticia completa", visible=False, render=False, interactive=False, placeholder="Aquí aparecerá el resumen de la noticia.", ), ], # title="⚔️ Clickbait Fighter! ⚔️", thumbnail="https://huggingface.co/spaces/Iker/ClickbaitFighter/resolve/main/logo2.png", theme="JohnSmith9982/small_and_pretty", description="""

Esta Inteligencia Artificial es capaz de generar un resumen de una sola frase que revela la verdad detrás de un titular sensacionalista o clickbait. Solo tienes que introducir la URL de la noticia. La IA accederá a la noticia, la leerá y en cuestión de segundos generará un resumen de una sola frase que revele la verdad detrás del titular.

🎚 Ajusta el nivel de resumen con el control deslizante. Cuanto maś alto, más corto será el resumen. ⌚ La IA se encuentra corriendo en un hardware bastante modesto, debería tardar menos de 30 segundos en generar el resumen, pero si muchos usuarios usan la app a la vez, tendrás que esperar tu turno. 💸 Este es un projecto sin ánimo de lucro, no se genera ningún tipo de ingreso con esta app. Los datos, la IA y el código se publicarán para su uso en la investigación académica. No puedes usar esta app para ningún uso comercial. 🧪 El modelo se encuentra en fase de desarrollo, si quieres ayudar a mejorarlo puedes usar los botones 👍 y 👎 para valorar el resumen. ¡Gracias por tu ayuda!""", article="Esta Inteligencia Artificial ha sido generada por Iker García-Ferrero. Puedes saber más sobre mi trabajo en mi [página web](https://ikergarcia1996.github.io/Iker-Garcia-Ferrero/) o mi perfil de [X](https://twitter.com/iker_garciaf). Puedes ponerte en contacto conmigo a través de correo electrónico (ver web) y X.", cache_examples=False, allow_flagging="manual", flagging_options=[("👍", "correct"), ("👎", "incorrect")], flagging_callback=hf_writer, concurrency_limit=20, ) demo.queue(max_size=None) demo.launch(share=False)