Hifzamudassar commited on
Commit
21d31fe
·
verified ·
1 Parent(s): d67f47d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +116 -208
app.py CHANGED
@@ -1,5 +1,5 @@
1
  # ============================== #
2
- # AI Study Wizard v2 #
3
  # ============================== #
4
 
5
  import os
@@ -11,7 +11,7 @@ import requests
11
  from PIL import Image, ImageDraw, ImageFont
12
  from gtts import gTTS
13
 
14
- # Safe MoviePy Imports for HuggingFace
15
  from moviepy.video.VideoClip import ImageClip
16
  from moviepy.audio.io.AudioFileClip import AudioFileClip
17
  from moviepy.video.compositing.concatenate import concatenate_videoclips
@@ -22,23 +22,20 @@ from pdf2image import convert_from_path
22
  import gradio as gr
23
  from urllib.parse import quote_plus
24
 
25
-
26
  # ==========================================================
27
- # HARD-CODED GROQ API KEY (Replace with your real API key)
28
  # ==========================================================
29
- GROQ_API_KEY = "YOUR_GROQ_API_KEYgsk_GHftv8pvXaU7yeIltEaxWGdyb3FYlEDMH09TDRgJz5yzGQdVE7Rf"
30
  GROQ_MODEL = "llama-3.3-70b-versatile"
31
 
32
-
33
  # ==========================================================
34
  # USERS DB / STATE
35
  # ==========================================================
36
  users_db = {}
37
  verification_codes = {}
38
 
39
-
40
  # ==========================================================
41
- # SIGNUP / VERIFY / LOGIN SYSTEM
42
  # ==========================================================
43
  def signup_user(username, email, password, contact):
44
  if email in users_db:
@@ -46,299 +43,210 @@ def signup_user(username, email, password, contact):
46
 
47
  code = str(random.randint(100000, 999999))
48
  verification_codes[email] = code
49
-
50
- users_db[email] = {
51
- "username": username,
52
- "password": password,
53
- "contact": contact,
54
- "verified": False
55
- }
56
-
57
  return "Signup successful! Your verification code:", code
58
 
59
-
60
  def verify_user(email, code):
61
- if email not in users_db:
62
- return "Email not found."
63
-
64
- if users_db[email]["verified"]:
65
- return "Already verified."
66
-
67
  if verification_codes.get(email) == code:
68
  users_db[email]["verified"] = True
69
  verification_codes.pop(email)
70
  return "Verification successful!"
71
-
72
  return "Invalid verification code."
73
 
74
-
75
  def login_user(email, password):
76
  user = users_db.get(email)
77
- if not user:
78
- return False, "User not found."
79
-
80
- if not user["verified"]:
81
- return False, "Account not verified."
82
-
83
- if user["password"] != password:
84
- return False, "Wrong password."
85
-
86
  return True, f"Welcome {user['username']}!"
87
 
88
-
89
  # ==========================================================
90
  # GROQ API CALL
91
  # ==========================================================
92
  def call_groq(prompt, max_tokens=600):
93
  url = "https://api.groq.com/openai/v1/chat/completions"
94
-
95
- headers = {
96
- "Authorization": f"Bearer {GROQ_API_KEY}",
97
- "Content-Type": "application/json"
98
- }
99
-
100
- payload = {
101
- "model": GROQ_MODEL,
102
- "messages": [{"role": "user", "content": prompt}],
103
- "max_tokens": max_tokens
104
- }
105
-
106
  try:
107
  r = requests.post(url, json=payload, headers=headers)
108
  return r.json()["choices"][0]["message"]["content"]
109
  except Exception as e:
110
  return f"Groq API Error: {e}"
111
 
112
-
 
 
113
  def answer_text_query(q):
114
- return call_groq(f"Answer very clearly:\n\n{q}")
115
-
 
 
 
 
116
 
117
  def generate_mcqs_from_text(text, n=5):
118
  return call_groq(f"Generate {n} MCQs with 4 options + correct answer:\n\n{text}")
119
 
120
-
121
  # ==========================================================
122
  # VIDEO GENERATION
123
  # ==========================================================
124
  def create_video_simple(text, tts_lang="en", preview=False):
125
-
126
- if not text.strip():
127
- return None
128
-
129
  tmp = tempfile.gettempdir()
130
  lines = [l.strip() for l in text.split("\n") if l.strip()]
131
- if preview:
132
- lines = lines[:1]
133
-
134
  clips = []
135
-
136
  for i, line in enumerate(lines):
137
  img_path = os.path.join(tmp, f"slide_{i}.png")
138
  audio_path = os.path.join(tmp, f"audio_{i}.mp3")
139
-
140
- # Slide image
141
- W, H = 480, 320
142
- img = Image.new("RGB", (W, H), (255, 182, 193))
143
  draw = ImageDraw.Draw(img)
144
-
145
- try:
146
- font = ImageFont.truetype("DejaVuSans-Bold.ttf", 22)
147
- except:
148
- font = ImageFont.load_default()
149
-
150
- draw.text((20, 20), line, fill="black", font=font)
151
  img.save(img_path)
152
-
153
  # Audio
154
  gTTS(text=line, lang=tts_lang).save(audio_path)
155
-
156
- duration = max(3, min(len(line) // 10 + 2, 8))
157
-
158
- clip = ImageClip(img_path).set_duration(duration)
159
- clip = clip.set_audio(AudioFileClip(audio_path))
160
  clips.append(clip)
161
-
162
  out_path = os.path.join(tmp, "prev.mp4" if preview else "full.mp4")
163
  final = concatenate_videoclips(clips, method="compose")
164
  final.write_videofile(out_path, fps=24, codec="libx264", audio_codec="aac", verbose=False)
165
-
166
  return out_path
167
 
168
-
169
  # ==========================================================
170
  # NOTES + FLOWCHART
171
  # ==========================================================
172
  def generate_notes_flowchart(text):
173
  notes = call_groq(f"Summarize into bullet study notes:\n\n{text}")
174
-
175
- img = Image.new("RGB", (480, 320), (144, 238, 144))
176
  draw = ImageDraw.Draw(img)
177
-
178
- try:
179
- font = ImageFont.truetype("DejaVuSans.ttf", 16)
180
- except:
181
- font = ImageFont.load_default()
182
-
183
  y = 20
184
  for line in notes.split("\n"):
185
- if y > 290:
186
- break
187
- draw.text((10, y), line, fill="black", font=font)
188
- y += 18
189
-
190
- return notes, img
191
-
192
 
193
  # ==========================================================
194
- # PDF + IMAGE OCR
195
  # ==========================================================
196
  def extract_text_from_file(file):
197
-
198
  if file.name.endswith(".pdf"):
199
  pages = convert_from_path(file.name)
200
- text = ""
201
  for page in pages:
202
  text += pytesseract.image_to_string(page) + "\n"
203
  return text
204
-
205
  else:
206
  return pytesseract.image_to_string(Image.open(file.name))
207
 
208
-
209
  # ==========================================================
210
  # LINKS
211
  # ==========================================================
212
- def get_youtube_link(q):
213
- return f"https://www.youtube.com/results?search_query={quote_plus(q)}"
214
-
215
-
216
- def get_google_link(q):
217
- return f"https://www.google.com/search?q={quote_plus(q)}"
218
-
219
-
220
  def get_links_clickable(topic):
221
  yt = "\n".join([f"[YouTube {i+1}]({get_youtube_link(topic)})" for i in range(3)])
222
  gg = "\n".join([f"[Google {i+1}]({get_google_link(topic)})" for i in range(3)])
223
- return yt, gg
224
-
225
 
226
  # ==========================================================
227
- # UI — GRADIENT BACKGROUND (Green + Light Pink)
228
  # ==========================================================
229
  custom_css = """
230
- body {
231
- background: linear-gradient(to bottom right, #90ee90, #ffb6c1);
232
- }
233
  """
234
 
235
-
236
  # ==========================================================
237
- # GRADIO UI
238
  # ==========================================================
239
  with gr.Blocks(css=custom_css) as demo:
 
240
 
241
- gr.Markdown("## 🌸 **AI Study Wizard** — Pink + Green Themed Student Assistant")
242
-
243
- # ---------------- SIGN UP ---------------- #
244
  with gr.Tab("Sign Up"):
245
- su_name = gr.Textbox(label="Username")
246
- su_email = gr.Textbox(label="Email")
247
- su_pass = gr.Textbox(label="Password", type="password")
248
- su_contact = gr.Textbox(label="Contact Number")
249
- su_btn = gr.Button("Sign Up")
250
-
251
- su_msg = gr.Textbox(label="Message", interactive=False)
252
- su_code = gr.Textbox(label="Your Verification Code", interactive=False)
253
-
254
- su_btn.click(signup_user, inputs=[su_name, su_email, su_pass, su_contact],
255
- outputs=[su_msg, su_code])
256
-
257
- # ---------------- VERIFY ---------------- #
258
  with gr.Tab("Verify"):
259
- v_email = gr.Textbox(label="Email")
260
- v_code = gr.Textbox(label="Verification Code")
261
- v_btn = gr.Button("Verify")
262
- v_msg = gr.Textbox(label="Status", interactive=False)
 
263
 
264
- v_btn.click(verify_user, inputs=[v_email, v_code], outputs=v_msg)
265
-
266
- # ---------------- LOGIN ---------------- #
267
  with gr.Tab("Login"):
268
- li_email = gr.Textbox(label="Email")
269
- li_pass = gr.Textbox(label="Password", type="password")
270
- li_btn = gr.Button("Login")
271
- li_msg = gr.Textbox(label="Login Status")
272
-
273
- def login_wrap(e, p):
274
- ok, msg = login_user(e, p)
275
- return msg
276
-
277
- li_btn.click(login_wrap, inputs=[li_email, li_pass], outputs=li_msg)
278
-
279
- # ---------------- QUESTION ---------------- #
280
  with gr.Tab("Ask Question"):
281
- q_in = gr.Textbox(label="Ask Any Question")
282
- a_out = gr.Textbox(label="Answer")
283
- m_out = gr.Textbox(label="MCQs")
284
- pv = gr.Video(label="Preview")
285
- fv = gr.Video(label="Full Video")
286
- ask_btn = gr.Button("Generate")
287
-
288
  def run_question(q):
289
- ans = answer_text_query(q)
290
- mcqs = generate_mcqs_from_text(ans)
291
- return ans, mcqs, create_video_simple(ans, preview=True), create_video_simple(ans)
 
292
 
293
- ask_btn.click(run_question, inputs=q_in, outputs=[a_out, m_out, pv, fv])
294
-
295
- # ---------------- UPLOAD ---------------- #
296
  with gr.Tab("Upload Document (PDF/Image)"):
297
-
298
- f_in = gr.File()
299
- options = gr.CheckboxGroup(["Extracted Text", "MCQs", "Video", "Notes"])
300
- lang = gr.Dropdown(["en", "ur", "hi"], value="en", label="Video Language")
301
-
302
- t_out = gr.Textbox(label="Extracted Text", lines=8)
303
- mc_out = gr.Textbox(label="MCQs", lines=8)
304
- pv2 = gr.Video(label="Preview Video")
305
- fv2 = gr.Video(label="Full Video")
306
- notes_out = gr.Textbox(label="Notes")
307
- flow_out = gr.Image(label="Flowchart")
308
-
309
- def process_file(file, opts, lg):
310
- text = extract_text_from_file(file)
311
-
312
- mcq = ""
313
- prev = None
314
- full = None
315
- notes = ""
316
- flow = None
317
-
318
- if "MCQs" in opts:
319
- mcq = generate_mcqs_from_text(text)
320
-
321
- if "Video" in opts:
322
- prev = create_video_simple(text, lg, preview=True)
323
- full = create_video_simple(text, lg)
324
-
325
- if "Notes" in opts:
326
- notes, flow = generate_notes_flowchart(text)
327
-
328
- return text, mcq, prev, full, notes, flow
329
-
330
- btn = gr.Button("Process")
331
- btn.click(process_file, inputs=[f_in, options, lang],
332
- outputs=[t_out, mc_out, pv2, fv2, notes_out, flow_out])
333
-
334
- # ---------------- LINKS ---------------- #
335
  with gr.Tab("Search Links"):
336
- topic = gr.Textbox(label="Topic")
337
- yt = gr.Markdown()
338
- gg = gr.Markdown()
339
- link_btn = gr.Button("Get Links")
340
-
341
- link_btn.click(get_links_clickable, inputs=topic, outputs=[yt, gg])
342
-
343
 
344
  demo.launch()
 
1
  # ============================== #
2
+ # AI Study Wizard v3 #
3
  # ============================== #
4
 
5
  import os
 
11
  from PIL import Image, ImageDraw, ImageFont
12
  from gtts import gTTS
13
 
14
+ # Safe MoviePy Imports
15
  from moviepy.video.VideoClip import ImageClip
16
  from moviepy.audio.io.AudioFileClip import AudioFileClip
17
  from moviepy.video.compositing.concatenate import concatenate_videoclips
 
22
  import gradio as gr
23
  from urllib.parse import quote_plus
24
 
 
25
  # ==========================================================
26
+ # HARD-CODED GROQ API KEY (Replace with your key)
27
  # ==========================================================
28
+ GROQ_API_KEY = "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"
29
  GROQ_MODEL = "llama-3.3-70b-versatile"
30
 
 
31
  # ==========================================================
32
  # USERS DB / STATE
33
  # ==========================================================
34
  users_db = {}
35
  verification_codes = {}
36
 
 
37
  # ==========================================================
38
+ # SIGNUP / VERIFY / LOGIN
39
  # ==========================================================
40
  def signup_user(username, email, password, contact):
41
  if email in users_db:
 
43
 
44
  code = str(random.randint(100000, 999999))
45
  verification_codes[email] = code
46
+ users_db[email] = {"username": username, "password": password, "contact": contact, "verified": False}
 
 
 
 
 
 
 
47
  return "Signup successful! Your verification code:", code
48
 
 
49
  def verify_user(email, code):
50
+ if email not in users_db: return "Email not found."
51
+ if users_db[email]["verified"]: return "Already verified."
 
 
 
 
52
  if verification_codes.get(email) == code:
53
  users_db[email]["verified"] = True
54
  verification_codes.pop(email)
55
  return "Verification successful!"
 
56
  return "Invalid verification code."
57
 
 
58
  def login_user(email, password):
59
  user = users_db.get(email)
60
+ if not user: return False, "User not found."
61
+ if not user["verified"]: return False, "Account not verified."
62
+ if user["password"] != password: return False, "Wrong password."
 
 
 
 
 
 
63
  return True, f"Welcome {user['username']}!"
64
 
 
65
  # ==========================================================
66
  # GROQ API CALL
67
  # ==========================================================
68
  def call_groq(prompt, max_tokens=600):
69
  url = "https://api.groq.com/openai/v1/chat/completions"
70
+ headers = {"Authorization": f"Bearer {GROQ_API_KEY}", "Content-Type": "application/json"}
71
+ payload = {"model": GROQ_MODEL, "messages":[{"role":"user","content":prompt}], "max_tokens": max_tokens}
 
 
 
 
 
 
 
 
 
 
72
  try:
73
  r = requests.post(url, json=payload, headers=headers)
74
  return r.json()["choices"][0]["message"]["content"]
75
  except Exception as e:
76
  return f"Groq API Error: {e}"
77
 
78
+ # ==========================================================
79
+ # ANSWER & MCQs
80
+ # ==========================================================
81
  def answer_text_query(q):
82
+ q = q.strip()
83
+ if len(q.split()) < 5:
84
+ prompt = f"Explain the following clearly and concisely for a beginner:\n\n{q}"
85
+ else:
86
+ prompt = f"Answer clearly:\n\n{q}"
87
+ return call_groq(prompt)
88
 
89
  def generate_mcqs_from_text(text, n=5):
90
  return call_groq(f"Generate {n} MCQs with 4 options + correct answer:\n\n{text}")
91
 
 
92
  # ==========================================================
93
  # VIDEO GENERATION
94
  # ==========================================================
95
  def create_video_simple(text, tts_lang="en", preview=False):
96
+ if not text.strip(): return None
 
 
 
97
  tmp = tempfile.gettempdir()
98
  lines = [l.strip() for l in text.split("\n") if l.strip()]
99
+ if preview: lines = lines[:1]
 
 
100
  clips = []
 
101
  for i, line in enumerate(lines):
102
  img_path = os.path.join(tmp, f"slide_{i}.png")
103
  audio_path = os.path.join(tmp, f"audio_{i}.mp3")
104
+ # Image
105
+ W, H = 480, 360
106
+ img = Image.new("RGB", (W,H), (255,182,193))
 
107
  draw = ImageDraw.Draw(img)
108
+ try: font = ImageFont.truetype("DejaVuSans-Bold.ttf", 22)
109
+ except: font = ImageFont.load_default()
110
+ draw.text((20,20), line, fill="black", font=font)
 
 
 
 
111
  img.save(img_path)
 
112
  # Audio
113
  gTTS(text=line, lang=tts_lang).save(audio_path)
114
+ duration = max(3, min(len(line)//10+2, 8))
115
+ clip = ImageClip(img_path).set_duration(duration).set_audio(AudioFileClip(audio_path))
 
 
 
116
  clips.append(clip)
 
117
  out_path = os.path.join(tmp, "prev.mp4" if preview else "full.mp4")
118
  final = concatenate_videoclips(clips, method="compose")
119
  final.write_videofile(out_path, fps=24, codec="libx264", audio_codec="aac", verbose=False)
 
120
  return out_path
121
 
 
122
  # ==========================================================
123
  # NOTES + FLOWCHART
124
  # ==========================================================
125
  def generate_notes_flowchart(text):
126
  notes = call_groq(f"Summarize into bullet study notes:\n\n{text}")
127
+ img = Image.new("RGB", (480,360), (144,238,144))
 
128
  draw = ImageDraw.Draw(img)
129
+ try: font = ImageFont.truetype("DejaVuSans.ttf", 16)
130
+ except: font = ImageFont.load_default()
 
 
 
 
131
  y = 20
132
  for line in notes.split("\n"):
133
+ if y>330: break
134
+ draw.text((10,y), line, fill="black", font=font)
135
+ y+=18
136
+ return notes,img
 
 
 
137
 
138
  # ==========================================================
139
+ # FILE OCR (PDF + IMAGE)
140
  # ==========================================================
141
  def extract_text_from_file(file):
 
142
  if file.name.endswith(".pdf"):
143
  pages = convert_from_path(file.name)
144
+ text=""
145
  for page in pages:
146
  text += pytesseract.image_to_string(page) + "\n"
147
  return text
 
148
  else:
149
  return pytesseract.image_to_string(Image.open(file.name))
150
 
 
151
  # ==========================================================
152
  # LINKS
153
  # ==========================================================
154
+ def get_youtube_link(q): return f"https://www.youtube.com/results?search_query={quote_plus(q)}"
155
+ def get_google_link(q): return f"https://www.google.com/search?q={quote_plus(q)}"
 
 
 
 
 
 
156
  def get_links_clickable(topic):
157
  yt = "\n".join([f"[YouTube {i+1}]({get_youtube_link(topic)})" for i in range(3)])
158
  gg = "\n".join([f"[Google {i+1}]({get_google_link(topic)})" for i in range(3)])
159
+ return yt,gg
 
160
 
161
  # ==========================================================
162
+ # GRADIENT BACKGROUND
163
  # ==========================================================
164
  custom_css = """
165
+ body {background: linear-gradient(to bottom right, #90ee90, #ffb6c1);}
 
 
166
  """
167
 
 
168
  # ==========================================================
169
+ # GRADIO APP
170
  # ==========================================================
171
  with gr.Blocks(css=custom_css) as demo:
172
+ gr.Markdown("## 🌸 **AI Study Wizard** — Pink + Green Themed")
173
 
174
+ # -------- SIGNUP -------- #
 
 
175
  with gr.Tab("Sign Up"):
176
+ su_name=gr.Textbox(label="Username")
177
+ su_email=gr.Textbox(label="Email")
178
+ su_pass=gr.Textbox(label="Password", type="password")
179
+ su_contact=gr.Textbox(label="Contact Number")
180
+ su_btn=gr.Button("Sign Up")
181
+ su_msg=gr.Textbox(label="Message", interactive=False)
182
+ su_code=gr.Textbox(label="Verification Code", interactive=False)
183
+ su_btn.click(signup_user, inputs=[su_name,su_email,su_pass,su_contact], outputs=[su_msg,su_code])
184
+
185
+ # -------- VERIFY -------- #
 
 
 
186
  with gr.Tab("Verify"):
187
+ v_email=gr.Textbox(label="Email")
188
+ v_code=gr.Textbox(label="Verification Code")
189
+ v_btn=gr.Button("Verify")
190
+ v_msg=gr.Textbox(label="Status", interactive=False)
191
+ v_btn.click(verify_user, inputs=[v_email,v_code], outputs=v_msg)
192
 
193
+ # -------- LOGIN -------- #
 
 
194
  with gr.Tab("Login"):
195
+ li_email=gr.Textbox(label="Email")
196
+ li_pass=gr.Textbox(label="Password", type="password")
197
+ li_btn=gr.Button("Login")
198
+ li_msg=gr.Textbox(label="Login Status")
199
+ def login_wrap(e,p): ok,msg=login_user(e,p); return msg
200
+ li_btn.click(login_wrap, inputs=[li_email,li_pass], outputs=li_msg)
201
+
202
+ # -------- QUESTION -------- #
 
 
 
 
203
  with gr.Tab("Ask Question"):
204
+ q_in=gr.Textbox(label="Ask Any Question")
205
+ a_out=gr.Textbox(label="Answer", lines=12)
206
+ m_out=gr.Textbox(label="MCQs", lines=12)
207
+ pv=gr.Video(label="Preview Video", width=640, height=360)
208
+ fv=gr.Video(label="Full Video", width=640, height=360)
209
+ ask_btn=gr.Button("Generate")
 
210
  def run_question(q):
211
+ ans=answer_text_query(q)
212
+ mcqs=generate_mcqs_from_text(ans)
213
+ return ans,mcqs,create_video_simple(ans,preview=True),create_video_simple(ans)
214
+ ask_btn.click(run_question, inputs=q_in, outputs=[a_out,m_out,pv,fv])
215
 
216
+ # -------- UPLOAD -------- #
 
 
217
  with gr.Tab("Upload Document (PDF/Image)"):
218
+ f_in=gr.File()
219
+ opts=gr.CheckboxGroup(["Extracted Text","MCQs","Video","Notes"])
220
+ lang=gr.Dropdown(["en","ur","hi"], value="en", label="Video Language")
221
+ t_out=gr.Textbox(label="Extracted Text", lines=12)
222
+ mc_out=gr.Textbox(label="MCQs", lines=12)
223
+ pv2=gr.Video(label="Preview Video", width=640, height=360)
224
+ fv2=gr.Video(label="Full Video", width=640, height=360)
225
+ notes_out=gr.Textbox(label="Notes", lines=12)
226
+ flow_out=gr.Image(label="Flowchart", type="pil")
227
+ def process_file(file, options, lg):
228
+ text=extract_text_from_file(file)
229
+ mcq=""
230
+ prev=None
231
+ full=None
232
+ notes=""
233
+ flow=None
234
+ if "MCQs" in options: mcq=generate_mcqs_from_text(text)
235
+ if "Video" in options:
236
+ prev=create_video_simple(text,lg,preview=True)
237
+ full=create_video_simple(text,lg)
238
+ if "Notes" in options:
239
+ notes,flow=generate_notes_flowchart(text)
240
+ return text,mcq,prev,full,notes,flow
241
+ btn=gr.Button("Process")
242
+ btn.click(process_file, inputs=[f_in,opts,lang], outputs=[t_out,mc_out,pv2,fv2,notes_out,flow_out])
243
+
244
+ # -------- LINKS -------- #
 
 
 
 
 
 
 
 
 
 
 
245
  with gr.Tab("Search Links"):
246
+ topic=gr.Textbox(label="Topic")
247
+ yt=gr.Markdown()
248
+ gg=gr.Markdown()
249
+ link_btn=gr.Button("Get Links")
250
+ link_btn.click(get_links_clickable, inputs=topic, outputs=[yt,gg])
 
 
251
 
252
  demo.launch()