CoolFace
Apppublic

NoticIA-Col/Generador-Noticias

sourceHugging Facemitupdated 1y agoView on Hugging Face
1likes
app.py334 linesDownload Raw Back to root
1import os2import openai3import whisper4import tempfile5import gradio as gr6from pydub import AudioSegment7import fitz  # PyMuPDF for handling PDFs8import docx  # For handling .docx files9import pandas as pd  # For handling .xlsx and .csv files10import requests11from bs4 import BeautifulSoup12from moviepy.editor import VideoFileClip13import yt_dlp14import logging15 16# Configure logging17logging.basicConfig(level=logging.INFO)18logger = logging.getLogger(__name__)19 20# Configure your OpenAI API key21openai.api_key = os.getenv("OPENAI_API_KEY")22 23# Load the highest quality Whisper model once24model = whisper.load_model("large")25 26def download_social_media_video(url):27    """Downloads a video from social media."""28    ydl_opts = {29        'format': 'bestaudio/best',30        'postprocessors': [{31            'key': 'FFmpegExtractAudio',32            'preferredcodec': 'mp3',33            'preferredquality': '192',34        }],35        'outtmpl': '%(id)s.%(ext)s',36    }37    try:38        with yt_dlp.YoutubeDL(ydl_opts) as ydl:39            info_dict = ydl.extract_info(url, download=True)40            audio_file = f"{info_dict['id']}.mp3"41        logger.info(f"Video successfully downloaded: {audio_file}")42        return audio_file43    except Exception as e:44        logger.error(f"Error downloading video: {str(e)}")45        raise46 47def convert_video_to_audio(video_file):48    """Converts a video file to audio."""49    try:50        video = VideoFileClip(video_file)51        with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as temp_file:52            video.audio.write_audiofile(temp_file.name)53            logger.info(f"Video converted to audio: {temp_file.name}")54            return temp_file.name55    except Exception as e:56        logger.error(f"Error converting video to audio: {str(e)}")57        raise58 59def preprocess_audio(audio_file):60    """Preprocesses the audio file to improve quality."""61    try:62        audio = AudioSegment.from_file(audio_file)63        audio = audio.apply_gain(-audio.dBFS + (-20))64        with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as temp_file:65            audio.export(temp_file.name, format="mp3")66            logger.info(f"Audio preprocessed: {temp_file.name}")67            return temp_file.name68    except Exception as e:69        logger.error(f"Error preprocessing audio file: {str(e)}")70        raise71 72def transcribe_audio(file):73    """Transcribes an audio or video file."""74    try:75        if isinstance(file, str) and file.startswith('http'):76            logger.info(f"Downloading social media video: {file}")77            file_path = download_social_media_video(file)78        elif isinstance(file, str) and file.lower().endswith(('.mp4', '.avi', '.mov', '.mkv')):79            logger.info(f"Converting local video to audio: {file}")80            file_path = convert_video_to_audio(file)81        else:82            logger.info(f"Preprocessing audio file: {file}")83            file_path = preprocess_audio(file)84 85        logger.info(f"Transcribing audio: {file_path}")86        result = model.transcribe(file_path)87        transcription = result.get("text", "Error in transcription")88        logger.info(f"Transcription completed: {transcription[:50]}...")89        return transcription90    except Exception as e:91        logger.error(f"Error processing file: {str(e)}")92        return f"Error processing file: {str(e)}"93 94def read_document(document_path):95    """Reads content from PDF, DOCX, XLSX or CSV documents."""96    try:97        if document_path.endswith(".pdf"):98            doc = fitz.open(document_path)99            return "\n".join([page.get_text() for page in doc])100        elif document_path.endswith(".docx"):101            doc = docx.Document(document_path)102            return "\n".join([paragraph.text for paragraph in doc.paragraphs])103        elif document_path.endswith(".xlsx"):104            return pd.read_excel(document_path).to_string()105        elif document_path.endswith(".csv"):106            return pd.read_csv(document_path).to_string()107        else:108            return "Unsupported file type. Please upload a PDF, DOCX, XLSX or CSV document."109    except Exception as e:110        return f"Error reading document: {str(e)}"111 112def read_url(url):113    """Reads content from a URL."""114    try:115        response = requests.get(url)116        response.raise_for_status()117        soup = BeautifulSoup(response.content, 'html.parser')118        return soup.get_text()119    except Exception as e:120        return f"Error reading URL: {str(e)}"121 122def process_social_content(url):123    """Processes content from a social media URL, handling both text and video."""124    try:125        # First, try to read content as text126        text_content = read_url(url)127 128        # Then, try to process as video129        try:130            video_content = transcribe_audio(url)131        except Exception:132            video_content = None133 134        return {135            "text": text_content,136            "video": video_content137        }138    except Exception as e:139        logger.error(f"Error processing social content: {str(e)}")140        return None141 142def generate_news(instructions, facts, size, tone, *args):143    """Generates a news article from instructions, facts, URLs, documents, transcriptions, and social media content."""144    knowledge_base = {145        "instructions": instructions,146        "facts": facts,147        "document_content": [],148        "audio_data": [],149        "url_content": [],150        "social_content": []151    }152    num_audios = 5 * 3  # 5 audios/videos * 3 fields (file, name, position)153    num_social_urls = 3 * 3  # 3 social media URLs * 3 fields (URL, name, context)154    num_urls = 5  # 5 general URLs155    audios = args[:num_audios]156    social_urls = args[num_audios:num_audios+num_social_urls]157    urls = args[num_audios+num_social_urls:num_audios+num_social_urls+num_urls]158    documents = args[num_audios+num_social_urls+num_urls:]159 160    for url in urls:161        if url:162            knowledge_base["url_content"].append(read_url(url))163 164    for document in documents:165        if document is not None:166            knowledge_base["document_content"].append(read_document(document.name))167 168    for i in range(0, len(audios), 3):169        audio_file, name, position = audios[i:i+3]170        if audio_file is not None:171            knowledge_base["audio_data"].append({"audio": audio_file, "name": name, "position": position})172 173    for i in range(0, len(social_urls), 3):174        social_url, social_name, social_context = social_urls[i:i+3]175        if social_url:176            social_content = process_social_content(social_url)177            if social_content:178                knowledge_base["social_content"].append({179                    "url": social_url,180                    "name": social_name,181                    "context": social_context,182                    "text": social_content["text"],183                    "video": social_content["video"]184                })185                logger.info(f"Social media content processed: {social_url}")186 187    transcriptions_text, raw_transcriptions = "", ""188 189    for idx, data in enumerate(knowledge_base["audio_data"]):190        if data["audio"] is not None:191            transcription = transcribe_audio(data["audio"])192            transcription_text = f'"{transcription}" - {data["name"]}, {data["position"]}'193            raw_transcription = f'[Audio/Video {idx + 1}]: "{transcription}" - {data["name"]}, {data["position"]}'194            transcriptions_text += transcription_text + "\n"195            raw_transcriptions += raw_transcription + "\n\n"196 197    for data in knowledge_base["social_content"]:198        if data["text"]:199            transcription_text = f'[Social media text]: "{data["text"][:200]}..." - {data["name"]}, {data["context"]}'200            transcriptions_text += transcription_text + "\n"201            raw_transcriptions += transcription_text + "\n\n"202        if data["video"]:203            transcription_video = f'[Social media video]: "{data["video"]}" - {data["name"]}, {data["context"]}'204            transcriptions_text += transcription_video + "\n"205            raw_transcriptions += transcription_video + "\n\n"206 207    document_content = "\n\n".join(knowledge_base["document_content"])208    url_content = "\n\n".join(knowledge_base["url_content"])209 210    internal_prompt = """211    Instructions for the model:212    - Follow news article principles: answer the 5 Ws in the first paragraph (Who?, What?, When?, Where?, Why?).213    - Ensure at least 80% of quotes are direct and in quotation marks.214    - The remaining 20% can be indirect quotes.215    - Don't invent new information.216    - Be rigorous with provided facts.217    - When processing uploaded documents, extract and highlight important quotes and testimonials from sources.218    - When processing uploaded documents, extract and highlight key figures.219    - Avoid using the date at the beginning of the news body. Start directly with the 5Ws.220    - Include social media content relevantly, citing the source and providing proper context.221    - Make sure to relate the provided context for social media content with its corresponding transcription or text.222    """223 224    prompt = f"""225    {internal_prompt}226    Write a news article with the following information, including a title, a 15-word hook (additional information that complements the title), and the content body with {size} words. The tone should be {tone}.227    Instructions: {knowledge_base["instructions"]}228    Facts: {knowledge_base["facts"]}229    Additional content from documents: {document_content}230    Additional content from URLs: {url_content}231    Use the following transcriptions as direct and indirect quotes (without changing or inventing content):232    {transcriptions_text}233    """234 235    try:236        response = openai.ChatCompletion.create(237            model="gpt-4o-mini",238            messages=[{"role": "user", "content": prompt}],239            temperature=0.1240        )241        news = response['choices'][0]['message']['content']242        return news, raw_transcriptions243    except Exception as e:244        logger.error(f"Error generating news article: {str(e)}")245        return f"Error generating news article: {str(e)}", ""246 247with gr.Blocks() as demo:248    gr.Markdown("## All-in-One News Generator")249    250    # Add tool description and attribution251    gr.Markdown("""252    ### About this tool253    254    This AI-powered news generator helps journalists and content creators produce news articles by processing multiple types of input:255    - Audio and video files with automatic transcription256    - Social media content257    - Documents (PDF, DOCX, XLSX, CSV)258    - Web URLs259    260    The tool uses advanced AI to generate well-structured news articles following journalistic principles and maintaining the integrity of source quotes.261    262    Created by [Camilo Vega](https://www.linkedin.com/in/camilo-vega-169084b1/), AI Consultant263    """)264    265    with gr.Row():266        with gr.Column(scale=2):267            instructions = gr.Textbox(label="News article instructions", lines=2)268            facts = gr.Textbox(label="Describe the news facts", lines=4)269            size = gr.Number(label="Content body size (in words)", value=100)270            tone = gr.Dropdown(label="News tone", choices=["serious", "neutral", "lighthearted"], value="neutral")271        with gr.Column(scale=3):272            inputs_list = [instructions, facts, size, tone]273            with gr.Tabs():274                for i in range(1, 6):275                    with gr.TabItem(f"Audio/Video {i}"):276                        file = gr.File(label=f"Audio/Video {i}", type="filepath", file_types=["audio", "video"])277                        name = gr.Textbox(label="Name", scale=1)278                        position = gr.Textbox(label="Position", scale=1)279                        inputs_list.extend([file, name, position])280                for i in range(1, 4):281                    with gr.TabItem(f"Social Media {i}"):282                        social_url = gr.Textbox(label=f"Social media URL {i}", lines=1)283                        social_name = gr.Textbox(label=f"Person/account name {i}", scale=1)284                        social_context = gr.Textbox(label=f"Content context {i}", lines=2)285                        inputs_list.extend([social_url, social_name, social_context])286                for i in range(1, 6):287                    with gr.TabItem(f"URL {i}"):288                        url = gr.Textbox(label=f"URL {i}", lines=1)289                        inputs_list.append(url)290                for i in range(1, 6):291                    with gr.TabItem(f"Document {i}"):292                        document = gr.File(label=f"Document {i}", type="filepath", file_count="single")293                        inputs_list.append(document)294 295    gr.Markdown("---")  # Visual separator296 297    with gr.Row():298        transcriptions_output = gr.Textbox(label="Transcriptions", lines=10)299 300    gr.Markdown("---")  # Visual separator301 302    with gr.Row():303        generate = gr.Button("Generate Draft")304    with gr.Row():305        news_output = gr.Textbox(label="Generated Draft", lines=20)306 307    generate.click(fn=generate_news, inputs=inputs_list, outputs=[news_output, transcriptions_output])308 309# Add description about how to use the app310gr.Markdown("""311### How to Use This App312 3131. **Input your requirements:**314   - Enter your news article instructions315   - Describe the key facts of your news story316   - Set the desired word count and tone317 3182. **Add your sources:**319   - Upload audio/video files for automatic transcription320   - Add social media URLs to extract content321   - Include web URLs for additional information322   - Upload documents (PDF, DOCX, XLSX, CSV) to extract relevant data323 3243. **Generate your draft:**325   - Click "Generate Draft" to create your news article326   - Review the transcriptions to verify source accuracy327   - Use the generated draft as a starting point for your news story328 329This tool helps streamline the news writing process by automatically gathering, organizing, and synthesizing information from multiple sources into a cohesive article that follows journalistic best practices.330 331Created by [Camilo Vega](https://www.linkedin.com/in/camilo-vega-169084b1/), AI Consultant332""")333 334demo.launch(share=True)