Spaces:
Configuration error
Configuration error
| import os | |
| import tempfile | |
| import random | |
| import requests | |
| from urllib.parse import quote_plus | |
| from PIL import Image, ImageDraw, ImageFont | |
| import pytesseract | |
| from gtts import gTTS | |
| from moviepy.editor import ImageClip, AudioFileClip, concatenate_videoclips | |
| import gradio as gr | |
| # =========================== | |
| # Environment Variables | |
| # =========================== | |
| GROQ_API_KEY = os.getenv("GROQ_API_KEY", "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") | |
| GROQ_MODEL = "llama-3.3-70b-versatile" | |
| if not GROQ_API_KEY: | |
| print("⚠️ WARNING: GROQ_API_KEY is missing. Add it in HuggingFace Secrets!") | |
| # =========================== | |
| # Users Database | |
| # =========================== | |
| users_db = {} | |
| verification_codes = {} | |
| # =========================== | |
| # Authentication Functions | |
| # =========================== | |
| def signup_user(username, email, password, contact): | |
| if email in users_db: | |
| return "Email already registered.", "" | |
| code = str(random.randint(100000, 999999)) | |
| verification_codes[email] = code | |
| users_db[email] = { | |
| "username": username, | |
| "password": password, | |
| "contact": contact, | |
| "verified": False | |
| } | |
| return "Signup successful! Verification code:", code | |
| def verify_user(email, code): | |
| if email not in users_db: | |
| return "Email not registered." | |
| if users_db[email]["verified"]: | |
| return "Already verified." | |
| if verification_codes.get(email) == code: | |
| users_db[email]["verified"] = True | |
| verification_codes.pop(email) | |
| return "Verification successful!" | |
| return "Invalid verification code." | |
| def login_user(email, password): | |
| user = users_db.get(email) | |
| if not user: | |
| return False, "User not found." | |
| if not user["verified"]: | |
| return False, "Account not verified." | |
| if user["password"] != password: | |
| return False, "Incorrect password." | |
| return True, f"Welcome {user['username']}!" | |
| # =========================== | |
| # Groq API Call | |
| # =========================== | |
| def call_groq(prompt, max_tokens=500): | |
| if not GROQ_API_KEY: | |
| return "❌ Missing GROQ_API_KEY in environment variables." | |
| url = "https://api.groq.com/openai/v1/chat/completions" | |
| headers = {"Authorization": f"Bearer {GROQ_API_KEY}", "Content-Type": "application/json"} | |
| payload = { | |
| "model": GROQ_MODEL, | |
| "messages": [{"role": "user", "content": prompt}], | |
| "max_tokens": max_tokens | |
| } | |
| try: | |
| r = requests.post(url, json=payload, headers=headers, timeout=20) | |
| if r.status_code == 200: | |
| return r.json()["choices"][0]["message"]["content"] | |
| return f"API Error {r.status_code}: {r.text}" | |
| except Exception as e: | |
| return f"API Exception: {e}" | |
| # =========================== | |
| # AI Helper Functions | |
| # =========================== | |
| def generate_mcqs_from_text(text, n=5): | |
| prompt = f"Create {n} MCQs with 4 options and answers:\n\n{text}" | |
| return call_groq(prompt) | |
| def answer_text_query(query): | |
| prompt = f"Answer clearly:\n\n{query}" | |
| return call_groq(prompt) | |
| # =========================== | |
| # Video Generator | |
| # =========================== | |
| def create_video_simple(text, tts_lang="en", preview=False): | |
| if not text.strip(): | |
| return None | |
| tmp = tempfile.gettempdir() | |
| lines = [l.strip() for l in text.split(".") if l.strip()] | |
| if preview: | |
| lines = lines[:1] # one slide preview | |
| clips = [] | |
| for i, chunk in enumerate(lines): | |
| slide_path = os.path.join(tmp, f"slide_{i}.png") | |
| # Create slide | |
| img = Image.new("RGB", (480, 320), (255, 182, 193)) | |
| draw = ImageDraw.Draw(img) | |
| font = ImageFont.load_default() | |
| draw.text((20, 20), "AI Generated Slide", fill="blue", font=font) | |
| draw.text((20, 80), chunk[:220], fill="black", font=font) | |
| img.save(slide_path) | |
| # Audio | |
| audio_path = os.path.join(tmp, f"audio_{i}.mp3") | |
| gTTS(text=chunk, lang=tts_lang).save(audio_path) | |
| # Clip | |
| clip = ImageClip(slide_path).set_duration(4) | |
| clip = clip.set_audio(AudioFileClip(audio_path)) | |
| clips.append(clip) | |
| output_path = os.path.join(tmp, f"video_preview.mp4" if preview else "video_full.mp4") | |
| video = concatenate_videoclips(clips) | |
| video.write_videofile(output_path, fps=24, codec="libx264", audio_codec="aac") | |
| return output_path | |
| # =========================== | |
| # Notes + Flowchart | |
| # =========================== | |
| def generate_notes_flowchart(text): | |
| notes = call_groq(f"Summarize into clean notes:\n\n{text}") | |
| img = Image.new("RGB", (500, 350), (180, 250, 180)) | |
| draw = ImageDraw.Draw(img) | |
| font = ImageFont.load_default() | |
| y = 20 | |
| for line in notes.split("\n"): | |
| draw.text((10, y), line[:60], fill="black", font=font) | |
| y += 18 | |
| if y > 300: | |
| break | |
| return notes, img | |
| # =========================== | |
| # Quick Search Links | |
| # =========================== | |
| def get_links(topic): | |
| yt = f"https://www.youtube.com/results?search_query={quote_plus(topic)}" | |
| gg = f"https://www.google.com/search?q={quote_plus(topic)}" | |
| return yt, gg | |
| # =========================== | |
| # UI | |
| # =========================== | |
| with gr.Blocks(title="AI Study Wizard") as demo: | |
| gr.Markdown("# 🎓 AI Study Wizard — Full Assistant") | |
| # Signup | |
| with gr.Tab("Sign Up"): | |
| name = gr.Textbox(label="Name") | |
| email = gr.Textbox(label="Email") | |
| pwd = gr.Textbox(label="Password", type="password") | |
| contact = gr.Textbox(label="Contact") | |
| btn = gr.Button("Create Account") | |
| msg = gr.Textbox(label="Message") | |
| code_out = gr.Textbox(label="Verification Code (demo)") | |
| btn.click(signup_user, [name, email, pwd, contact], [msg, code_out]) | |
| # Verify | |
| with gr.Tab("Verify"): | |
| v_email = gr.Textbox(label="Email") | |
| v_code = gr.Textbox(label="Code") | |
| v_btn = gr.Button("Verify") | |
| v_msg = gr.Textbox(label="Status") | |
| v_btn.click(verify_user, [v_email, v_code], v_msg) | |
| # Login | |
| with gr.Tab("Login"): | |
| l_email = gr.Textbox(label="Email") | |
| l_pass = gr.Textbox(label="Password", type="password") | |
| l_btn = gr.Button("Login") | |
| l_msg = gr.Textbox(label="Message") | |
| l_btn.click(lambda e, p: login_user(e, p), [l_email, l_pass], l_msg) | |
| # Ask Question | |
| with gr.Tab("Ask AI"): | |
| q = gr.Textbox(label="Your Question") | |
| ans = gr.Textbox(label="Answer", lines=8) | |
| mcq = gr.Textbox(label="MCQs", lines=8) | |
| pv = gr.Video(label="Preview Video") | |
| fv = gr.Video(label="Full Video") | |
| b = gr.Button("Generate") | |
| def process_query(q): | |
| a = answer_text_query(q) | |
| m = generate_mcqs_from_text(a) | |
| prev = create_video_simple(a, preview=True) | |
| full = create_video_simple(a, preview=False) | |
| return a, m, prev, full | |
| b.click(process_query, q, [ans, mcq, pv, fv]) | |
| # Upload Notes | |
| with gr.Tab("Upload Image"): | |
| file = gr.File(label="Upload Image") | |
| lang = gr.Dropdown(["en", "ur", "hi"], value="en") | |
| out_text = gr.Textbox(label="Extracted Text", lines=6) | |
| out_mcq = gr.Textbox(label="MCQs", lines=6) | |
| out_notes = gr.Textbox(label="Notes", lines=6) | |
| out_flow = gr.Image(label="Flowchart") | |
| out_prev = gr.Video(label="Preview Video") | |
| out_full = gr.Video(label="Full Video") | |
| def process_upload(f, language): | |
| try: | |
| text = pytesseract.image_to_string(Image.open(f.name)) | |
| except: | |
| text = "" | |
| mcqs = generate_mcqs_from_text(text) if text else "" | |
| notes, img = generate_notes_flowchart(text) if text else ("", None) | |
| prev = create_video_simple(text, tts_lang=language, preview=True) if text else None | |
| full = create_video_simple(text, tts_lang=language, preview=False) if text else None | |
| return text, mcqs, notes, img, prev, full | |
| btn = gr.Button("Process") | |
| btn.click(process_upload, [file, lang], | |
| [out_text, out_mcq, out_notes, out_flow, out_prev, out_full]) | |
| # Search Links | |
| with gr.Tab("Search"): | |
| topic = gr.Textbox(label="Topic") | |
| yt = gr.Textbox(label="YouTube", interactive=False) | |
| gg = gr.Textbox(label="Google", interactive=False) | |
| btn = gr.Button("Search") | |
| btn.click(get_links, topic, [yt, gg]) | |
| demo.launch() |