From 9739dfd43e7390ff318f5acb2c2e2beb866c964f Mon Sep 17 00:00:00 2001 From: priyanshm07 Date: Thu, 17 Apr 2025 19:31:40 +0530 Subject: [PATCH] Add Blog to Podcast Generator Agent --- .../ai_blog_to_podcast_agent/README.md | 52 +++++++++ .../blog_to_podcast_agent.py | 100 ++++++++++++++++++ .../ai_blog_to_podcast_agent/requirements.txt | 6 ++ 3 files changed, 158 insertions(+) create mode 100644 ai_agent_tutorials/ai_blog_to_podcast_agent/README.md create mode 100644 ai_agent_tutorials/ai_blog_to_podcast_agent/blog_to_podcast_agent.py create mode 100644 ai_agent_tutorials/ai_blog_to_podcast_agent/requirements.txt diff --git a/ai_agent_tutorials/ai_blog_to_podcast_agent/README.md b/ai_agent_tutorials/ai_blog_to_podcast_agent/README.md new file mode 100644 index 0000000..7a4bd03 --- /dev/null +++ b/ai_agent_tutorials/ai_blog_to_podcast_agent/README.md @@ -0,0 +1,52 @@ +## 📰 ➡️ 🎙️ Blog to Podcast Agent +This is a Streamlit-based application that allows users to convert any blog post into a podcast. The app uses OpenAI's GPT-4 model for summarization, Firecrawl for scraping blog content, and ElevenLabs API for generating audio. Users simply input a blog URL, and the app will generate a podcast episode based on the blog. + +## Features + +- **Blog Scraping**: Scrapes the full content of any public blog URL using Firecrawl API. + +- **Summary Generation**: Creates an engaging and concise summary of the blog (within 2000 characters) using OpenAI GPT-4. + +- **Podcast Generation**: Converts the summary into an audio podcast using the ElevenLabs voice API. + +- **API Key Integration**: Requires OpenAI, Firecrawl, and ElevenLabs API keys to function, entered securely via the sidebar. + +## Setup + +### Requirements + +1. **API Keys**: + - **OpenAI API Key**: Sign up at OpenAI to obtain your API key. + + - **ElevenLabs API Key**: Get your ElevenLabs API key from ElevenLabs. + + - **Firecrawl API Key**: Get your Firecrawl API key from Firecrawl. + +2. **Python 3.8+**: Ensure you have Python 3.8 or higher installed. + +### Installation +1. Clone this repository: + ```bash + git clone https://github.com/Shubhamsaboo/awesome-llm-apps + cd ai_agent_tutorials/ai_blog_to_podcast_agent + ``` + +2. Install the required Python packages: + ```bash + pip install -r requirements.txt + ``` +### Running the App + +1. Start the Streamlit app: + ```bash + streamlit run blog_to_podcast_agent.py + ``` + +2. In the app interface: + - Enter your OpenAI, ElevenLabs, and Firecrawl API keys in the sidebar. + + - Input the blog URL you want to convert. + + - Click "🎙️ Generate Podcast". + + - Listen to the generated podcast or download it. \ No newline at end of file diff --git a/ai_agent_tutorials/ai_blog_to_podcast_agent/blog_to_podcast_agent.py b/ai_agent_tutorials/ai_blog_to_podcast_agent/blog_to_podcast_agent.py new file mode 100644 index 0000000..1947967 --- /dev/null +++ b/ai_agent_tutorials/ai_blog_to_podcast_agent/blog_to_podcast_agent.py @@ -0,0 +1,100 @@ +import os +from uuid import uuid4 +from agno.agent import Agent +from agno.models.openai import OpenAIChat +from agno.tools.eleven_labs import ElevenLabsTools +from agno.tools.firecrawl import FirecrawlTools +from agno.agent import Agent, RunResponse +from agno.utils.audio import write_audio_to_file +from agno.utils.log import logger +import streamlit as st + +# Streamlit Page Setup +st.set_page_config(page_title="📰 ➡️ 🎙️ Blog to Podcast Agent", page_icon="🎙️") +st.title("📰 ➡️ 🎙️ Blog to Podcast Agent") + +# Sidebar: API Keys +st.sidebar.header("🔑 API Keys") + +openai_api_key = st.sidebar.text_input("OpenAI API Key", type="password") +elevenlabs_api_key = st.sidebar.text_input("ElevenLabs API Key", type="password") +firecrawl_api_key = st.sidebar.text_input("Firecrawl API Key", type="password") + +# Check if all keys are provided +keys_provided = all([openai_api_key, elevenlabs_api_key, firecrawl_api_key]) + +# Input: Blog URL +url = st.text_input("Enter the Blog URL:", "") + +# Button: Generate Podcast +generate_button = st.button("🎙️ Generate Podcast", disabled=not keys_provided) + +if not keys_provided: + st.warning("Please enter all required API keys to enable podcast generation.") + +if generate_button: + if url.strip() == "": + st.warning("Please enter a blog URL first.") + else: + # Set API keys as environment variables for Agno and Tools + os.environ["OPENAI_API_KEY"] = openai_api_key + os.environ["ELEVENLABS_API_KEY"] = elevenlabs_api_key + os.environ["FIRECRAWL_API_KEY"] = firecrawl_api_key + + with st.spinner("Processing... Scraping blog, summarizing and generating podcast 🎶"): + try: + blog_to_podcast_agent = Agent( + name="Blog to Podcast Agent", + agent_id="blog_to_podcast_agent", + model=OpenAIChat(id="gpt-4o"), + tools=[ + ElevenLabsTools( + voice_id="JBFqnCBsd6RMkjVDRZzb", + model_id="eleven_multilingual_v2", + target_directory="audio_generations", + ), + FirecrawlTools(), + ], + description="You are an AI agent that can generate audio using the ElevenLabs API.", + instructions=[ + "When the user provides a blog URL:", + "1. Use FirecrawlTools to scrape the blog content", + "2. Create a concise summary of the blog content that is NO MORE than 2000 characters long", + "3. The summary should capture the main points while being engaging and conversational", + "4. Use the ElevenLabsTools to convert the summary to audio", + "Ensure the summary is within the 2000 character limit to avoid ElevenLabs API limits", + ], + markdown=True, + debug_mode=True, + ) + + podcast: RunResponse = blog_to_podcast_agent.run( + f"Convert the blog content to a podcast: {url}" + ) + + save_dir = "audio_generations" + os.makedirs(save_dir, exist_ok=True) + + if podcast.audio and len(podcast.audio) > 0: + filename = f"{save_dir}/podcast_{uuid4()}.wav" + write_audio_to_file( + audio=podcast.audio[0].base64_audio, + filename=filename + ) + + st.success("Podcast generated successfully! 🎧") + audio_bytes = open(filename, "rb").read() + st.audio(audio_bytes, format="audio/wav") + + st.download_button( + label="Download Podcast", + data=audio_bytes, + file_name="generated_podcast.wav", + mime="audio/wav" + ) + else: + st.error("No audio was generated. Please try again.") + + except Exception as e: + st.error(f"An error occurred: {e}") + logger.error(f"Streamlit app error: {e}") diff --git a/ai_agent_tutorials/ai_blog_to_podcast_agent/requirements.txt b/ai_agent_tutorials/ai_blog_to_podcast_agent/requirements.txt new file mode 100644 index 0000000..b3bd145 --- /dev/null +++ b/ai_agent_tutorials/ai_blog_to_podcast_agent/requirements.txt @@ -0,0 +1,6 @@ +agno==1.2.8 +streamlit==1.44.1 +openai +Requests +firecrawl +elevenlabs \ No newline at end of file