import requests from bs4 import BeautifulSoup import os from dotenv import load_dotenv from groq import Groq import gradio as gr from youtube_transcript_api import YouTubeTranscriptApi # ------------------------------- # LOAD KEYS # ------------------------------- load_dotenv() BRIGHTDATA_API_KEY = os.getenv("BRIGHTDATA_API_KEY") GROQ_API_KEY = os.getenv("GROQ_API_KEY") client = Groq(api_key=GROQ_API_KEY) # ============================================================ # TAB 1: SIMPLE GOODREADS SCRAPER # ============================================================ def get_books(): headers = { "Authorization": f"Bearer {BRIGHTDATA_API_KEY}", "Content-Type": "application/json" } data = { "zone": "web_unlocker2", "url": "https://www.goodreads.com/list/show/1.Best_Books_Ever", "format": "raw" } response = requests.post("https://api.brightdata.com/request", json=data, headers=headers) soup = BeautifulSoup(response.text, "html.parser") books = soup.select("tr[itemtype='http://schema.org/Book']") results = [] for b in books[:10]: try: results.append({ "title": b.select_one("a.bookTitle span").text.strip(), "author": b.select_one("a.authorName span").text.strip(), "rating": b.select_one("span.minirating").text.strip() }) except: pass return results books_data = get_books() def ask_books(question, history): context = str(books_data) res = client.chat.completions.create( model="llama-3.1-8b-instant", messages=[ {"role": "system", "content": f"Answer ONLY from this data: {context}"}, {"role": "user", "content": question} ] ) return res.choices[0].message.content # ============================================================ # TAB 2: SIMPLE YOUTUBE TRANSCRIPT # ============================================================ current_transcript = "" def load_transcript(video_id): global current_transcript try: if "youtube.com" in video_id: video_id = video_id.split("v=")[-1] elif "youtu.be" in video_id: video_id = video_id.split("/")[-1] data = YouTubeTranscriptApi().fetch(video_id) current_transcript = " ".join([x.text for x in data]) return "✅ Transcript loaded" except: return "❌ Transcript not available" def ask_youtube(question, history): if not current_transcript: return "⚠️ Load transcript first" res = client.chat.completions.create( model="llama-3.1-8b-instant", messages=[ {"role": "system", "content": f"Answer ONLY from this: {current_transcript[:5000]}"}, {"role": "user", "content": question} ] ) return res.choices[0].message.content # ============================================================ # UI # ============================================================ with gr.Blocks() as app: gr.Markdown("# 🤖 AI Q&A Bot (Ver 2)") with gr.Tabs(): # TAB 1 with gr.Tab("📚 Books"): gr.Markdown("Ask questions about Goodreads books") gr.ChatInterface( fn=ask_books, examples=[ "What is the top book?", "Who wrote second book?" ] ) # TAB 2 with gr.Tab("🎬 YouTube"): vid = gr.Textbox(label="Enter YouTube URL or ID") status = gr.Textbox(label="Status") btn = gr.Button("Load Transcript") btn.click(load_transcript, inputs=vid, outputs=status) gr.ChatInterface(fn=ask_youtube) app.launch()