Spaces:
Sleeping
Sleeping
| import os, tempfile, random, pytesseract, requests | |
| from PIL import Image, ImageDraw, ImageFont | |
| from gtts import gTTS | |
| from moviepy.video.VideoClip import ImageClip | |
| from moviepy.audio.io.AudioFileClip import AudioFileClip | |
| from moviepy.video.compositing.concatenate import concatenate_videoclips | |
| from pdf2image import convert_from_path | |
| import gradio as gr | |
| from urllib.parse import quote_plus | |
| # ===================== | |
| # HARD-CODED API KEY | |
| # ===================== | |
| GROQ_API_KEY = "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" | |
| GROQ_MODEL = "llama-3.3-70b-versatile" | |
| # ===================== | |
| # USERS DB | |
| # ===================== | |
| users_db = {} | |
| verification_codes = {} | |
| # ===================== | |
| # SIGNUP / VERIFY / LOGIN | |
| # ===================== | |
| 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! Your verification code:", code | |
| def verify_user(email,code): | |
| if email not in users_db: return "Email not found." | |
| 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,"Wrong password." | |
| return True,f"Welcome {user['username']}!" | |
| # ===================== | |
| # GROQ API | |
| # ===================== | |
| def call_groq(prompt,max_tokens=600): | |
| 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=30) | |
| return r.json()["choices"][0]["message"]["content"] | |
| except Exception as e: | |
| return f"Groq API Error: {e}" | |
| # ===================== | |
| # ANSWERS / MCQs | |
| # ===================== | |
| def answer_text_query(q): | |
| q = q.strip() | |
| if len(q.split()) < 6: | |
| prompt=f"Explain clearly in detail for beginners:\n\n{q}" | |
| else: | |
| prompt=f"Answer concisely:\n\n{q}" | |
| return call_groq(prompt) | |
| def generate_mcqs_from_text(text,n=5): | |
| return call_groq(f"Generate {n} MCQs with 4 options + correct answer:\n\n{text}") | |
| # ===================== | |
| # VIDEO | |
| # ===================== | |
| 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.splitlines() if l.strip()] or [p.strip() for p in text.split('.') if p.strip()] | |
| if preview: lines=lines[:1] | |
| clips=[] | |
| for i,line in enumerate(lines): | |
| W,H=480,360 | |
| img_path=os.path.join(tmp,f"slide_{i}.png") | |
| audio_path=os.path.join(tmp,f"audio_{i}.mp3") | |
| img=Image.new("RGB",(W,H),(255,182,193)) | |
| draw=ImageDraw.Draw(img) | |
| try: font=ImageFont.truetype("DejaVuSans-Bold.ttf",22) | |
| except: font=ImageFont.load_default() | |
| draw.text((20,20),line,fill="black",font=font) | |
| img.save(img_path) | |
| gTTS(text=line,lang=tts_lang).save(audio_path) | |
| duration=max(3,min(len(line)//10+3,10)) | |
| clip=ImageClip(img_path).set_duration(duration).set_audio(AudioFileClip(audio_path)) | |
| clips.append(clip) | |
| out=os.path.join(tmp,"preview.mp4" if preview else "full.mp4") | |
| final=concatenate_videoclips(clips,method="compose") | |
| final.write_videofile(out,fps=24,codec="libx264",audio_codec="aac",verbose=False) | |
| return out | |
| # ===================== | |
| # NOTES & FLOWCHART | |
| # ===================== | |
| def generate_notes_flowchart(text): | |
| notes=call_groq(f"Summarize into bullet study notes:\n\n{text}") | |
| img=Image.new("RGB",(480,360),(144,238,144)) | |
| draw=ImageDraw.Draw(img) | |
| try: font=ImageFont.truetype("DejaVuSans.ttf",16) | |
| except: font=ImageFont.load_default() | |
| y=20 | |
| for line in notes.split("\n"): | |
| if y>330: break | |
| draw.text((10,y),line,fill="black",font=font) | |
| y+=18 | |
| return notes,img | |
| # ===================== | |
| # FILE OCR (Safe) | |
| # ===================== | |
| def extract_text_from_file(file): | |
| try: | |
| if file.name.endswith(".pdf"): | |
| pages=convert_from_path(file.name) | |
| text="" | |
| for page in pages: | |
| text+=pytesseract.image_to_string(page)+"\n" | |
| return text | |
| else: | |
| img = Image.open(file.name) | |
| return pytesseract.image_to_string(img) | |
| except Exception as e: | |
| return f"Error reading file: {e}" | |
| # ===================== | |
| # LINKS | |
| # ===================== | |
| def get_youtube_link(q): return f"https://www.youtube.com/results?search_query={quote_plus(q)}" | |
| def get_google_link(q): return f"https://www.google.com/search?q={quote_plus(q)}" | |
| def get_links_clickable(topic): | |
| yt="\n".join([f"[YouTube {i+1}]({get_youtube_link(topic)})" for i in range(3)]) | |
| gg="\n".join([f"[Google {i+1}]({get_google_link(topic)})" for i in range(3)]) | |
| return yt,gg | |
| # ===================== | |
| # GRADIENT BACKGROUND | |
| # ===================== | |
| custom_css=""" | |
| body {background: linear-gradient(to bottom right, #90ee90, #ffb6c1);} | |
| """ | |
| # ===================== | |
| # UPLOAD PROCESS (Fixed) | |
| # ===================== | |
| def process_file(file, options, lg): | |
| text="" | |
| mcq="" | |
| prev=None | |
| full=None | |
| notes="" | |
| flow=None | |
| if file is None: | |
| return "No file uploaded.","",None,None,"",None | |
| # Extract text safely | |
| try: | |
| if file.name.endswith(".pdf"): | |
| pages=convert_from_path(file.name) | |
| for page in pages: | |
| text+=pytesseract.image_to_string(page)+"\n" | |
| else: | |
| img = Image.open(file.name) | |
| text = pytesseract.image_to_string(img) | |
| except Exception as e: | |
| text=f"Error extracting text: {e}" | |
| # Generate MCQs | |
| if "MCQs" in options and text.strip(): | |
| try: | |
| mcq = generate_mcqs_from_text(text) | |
| except Exception as e: | |
| mcq=f"Error generating MCQs: {e}" | |
| # Generate Video | |
| if "Video" in options and text.strip(): | |
| try: | |
| prev=create_video_simple(text,lg,preview=True) | |
| full=create_video_simple(text,lg) | |
| except Exception as e: | |
| prev=None | |
| full=None | |
| text += f"\n[Video error: {e}]" | |
| # Generate Notes & Flowchart | |
| if "Notes" in options and text.strip(): | |
| try: | |
| notes,flow = generate_notes_flowchart(text) | |
| except Exception as e: | |
| notes="" | |
| flow=None | |
| text += f"\n[Notes/Flowchart error: {e}]" | |
| return text, mcq, prev, full, notes, flow | |
| # ===================== | |
| # GRADIO UI | |
| # ===================== | |
| with gr.Blocks() as demo: | |
| gr.HTML(f"<style>{custom_css}</style>") | |
| gr.Markdown("## 🌸 AI Study Wizard — Pink + Green Gradient") | |
| # SIGNUP | |
| with gr.Tab("Sign Up"): | |
| su_name=gr.Textbox(label="Username") | |
| su_email=gr.Textbox(label="Email") | |
| su_pass=gr.Textbox(label="Password",type="password") | |
| su_contact=gr.Textbox(label="Contact Number") | |
| su_btn=gr.Button("Sign Up") | |
| su_msg=gr.Textbox(label="Message",interactive=False) | |
| su_code=gr.Textbox(label="Verification Code",interactive=False) | |
| su_btn.click(signup_user,[su_name,su_email,su_pass,su_contact],[su_msg,su_code]) | |
| # VERIFY | |
| with gr.Tab("Verify"): | |
| v_email=gr.Textbox(label="Email") | |
| v_code=gr.Textbox(label="Verification Code") | |
| v_btn=gr.Button("Verify") | |
| v_msg=gr.Textbox(label="Status",interactive=False) | |
| v_btn.click(verify_user,[v_email,v_code],v_msg) | |
| # LOGIN | |
| with gr.Tab("Login"): | |
| li_email=gr.Textbox(label="Email") | |
| li_pass=gr.Textbox(label="Password",type="password") | |
| li_btn=gr.Button("Login") | |
| li_msg=gr.Textbox(label="Login Status") | |
| def login_wrap(e,p): ok,msg=login_user(e,p); return msg | |
| li_btn.click(login_wrap,[li_email,li_pass],li_msg) | |
| # ASK QUESTION | |
| with gr.Tab("Ask Question"): | |
| q_in=gr.Textbox(label="Ask Question") | |
| a_out=gr.Textbox(label="Answer",lines=12) | |
| m_out=gr.Textbox(label="MCQs",lines=12) | |
| pv=gr.Video(label="Preview Video",width=640,height=360) | |
| fv=gr.Video(label="Full Video",width=640,height=360) | |
| ask_btn=gr.Button("Generate") | |
| def run_question(q): | |
| ans=answer_text_query(q) | |
| mcqs=generate_mcqs_from_text(ans) | |
| return ans,mcqs,create_video_simple(ans,preview=True),create_video_simple(ans) | |
| ask_btn.click(run_question,q_in,[a_out,m_out,pv,fv]) | |
| # UPLOAD | |
| with gr.Tab("Upload PDF/Image"): | |
| f_in=gr.File() | |
| opts=gr.CheckboxGroup(["Extracted Text","MCQs","Video","Notes"]) | |
| lang=gr.Dropdown(["en","ur","hi"],value="en",label="Video Language") | |
| t_out=gr.Textbox(label="Extracted Text",lines=12) | |
| mc_out=gr.Textbox(label="MCQs",lines=12) | |
| pv2=gr.Video(label="Preview Video",width=640,height=360) | |
| fv2=gr.Video(label="Full Video",width=640,height=360) | |
| notes_out=gr.Textbox(label="Notes",lines=12) | |
| flow_out=gr.Image(label="Flowchart",type="pil") | |
| btn=gr.Button("Process") | |
| btn.click(process_file,[f_in,opts,lang],[t_out,mc_out,pv2,fv2,notes_out,flow_out]) | |
| # LINKS | |
| with gr.Tab("Search Links"): | |
| topic=gr.Textbox(label="Topic") | |
| yt=gr.Markdown() | |
| gg=gr.Markdown() | |
| link_btn=gr.Button("Get Links") | |
| link_btn.click(get_links_clickable,topic,[yt,gg]) | |
| demo.launch() |