AIStudyWizard / app.py
Hifzamudassar's picture
Update app.py
72d16f0 verified
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()