Hifzamudassar commited on
Commit
72d16f0
·
verified ·
1 Parent(s): 84ca952

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +227 -230
app.py CHANGED
@@ -1,272 +1,269 @@
1
- # =========================== #
2
- # Install Packages #
3
- # =========================== #
4
- import os, tempfile, random
 
5
  from PIL import Image, ImageDraw, ImageFont
6
  import pytesseract
7
  from gtts import gTTS
8
  from moviepy.editor import ImageClip, AudioFileClip, concatenate_videoclips
9
  import gradio as gr
10
- from urllib.parse import quote_plus
11
- import requests
12
 
13
- # =========================== #
14
- # Users DB & States #
15
- # =========================== #
 
 
 
 
 
 
 
 
 
 
16
  users_db = {}
17
  verification_codes = {}
18
 
19
- # =========================== #
20
- # Signup & Verification #
21
- # =========================== #
22
- def signup_user(username,email,password,contact):
 
23
  if email in users_db:
24
- return "Email already registered. Please login.", ""
25
- code = str(random.randint(100000,999999))
26
  verification_codes[email] = code
27
- users_db[email] = {"username":username,"password":password,"contact":contact,"verified":False}
28
- return f"Signup successful! Your verification code (demo) is:", code
29
 
30
- def verify_user(email,code):
 
 
 
 
 
 
 
 
 
 
31
  if email not in users_db:
32
- return "Email not found."
33
  if users_db[email]["verified"]:
34
  return "Already verified."
 
35
  if verification_codes.get(email) == code:
36
  users_db[email]["verified"] = True
37
  verification_codes.pop(email)
38
- return "Verification successful! You can now login."
39
  return "Invalid verification code."
40
 
41
- def login_user(email,password):
 
42
  user = users_db.get(email)
43
- if not user: return False,"User not found."
44
- if not user["verified"]: return False,"Not verified."
45
- if user["password"] != password: return False,"Incorrect password."
46
- return True,f"Welcome {user['username']}!"
47
-
48
- # =========================== #
49
- # Groq API Functions #
50
- # =========================== #
51
- GROQ_API_KEY = "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"
52
- GROQ_MODEL = "llama-3.3-70b-versatile"
 
 
 
 
 
53
 
54
- def call_groq(prompt,max_tokens=600):
55
  url = "https://api.groq.com/openai/v1/chat/completions"
56
- headers = {"Authorization":f"Bearer {GROQ_API_KEY}", "Content-Type":"application/json"}
 
57
  payload = {
58
- "model":GROQ_MODEL,
59
- "messages":[{"role":"user","content":prompt}],
60
- "max_tokens":max_tokens
61
  }
 
62
  try:
63
- r = requests.post(url,json=payload,headers=headers,timeout=30)
64
  if r.status_code == 200:
65
- return r.json().get("choices",[{}])[0].get("message",{}).get("content","")
66
- return f"[Model error {r.status_code}] {r.text}"
67
  except Exception as e:
68
- return f"[API error] {e}"
69
 
70
- def generate_mcqs_from_text(text,n=5):
71
- if not text.strip(): return "No text provided."
72
- prompt=f"Create {n} MCQs with 4 options and correct answer:\n\n{text}"
 
 
 
73
  return call_groq(prompt)
74
 
 
75
  def answer_text_query(query):
76
- if not query.strip(): return "No question provided."
77
- prompt=f"Answer clearly and concisely:\n\n{query}"
78
  return call_groq(prompt)
79
 
80
- # =========================== #
81
- # Video Generation #
82
- # =========================== #
83
- def create_video_simple(text,tts_lang="en",preview=False):
84
- if not text.strip(): return None
85
- tmp=tempfile.gettempdir()
86
- lines=[l.strip() for l in text.splitlines() if l.strip()] or [p.strip() for p in text.split('.') if p.strip()]
87
- if preview: lines=lines[:1]
88
-
89
- max_slides = 3 if not preview else 1
90
- chunk_size = max(1,(len(lines)+max_slides-1)//max_slides)
91
- clips=[]
92
- try:
93
- for i in range(0,len(lines),chunk_size):
94
- chunk = " ".join(lines[i:i+chunk_size]).strip()
95
- if not chunk: continue
96
- slide_path=os.path.join(tmp,f"slide_{i}.png")
97
- W,H=(480,320)
98
- img=Image.new("RGB",(W,H),(255,182,193))
99
- draw=ImageDraw.Draw(img)
100
 
101
- try:
102
- font = ImageFont.truetype("DejaVuSans-Bold.ttf",18)
103
- title_font = ImageFont.truetype("DejaVuSans-Bold.ttf",24)
104
- except:
105
- font=ImageFont.load_default()
106
- title_font=ImageFont.load_default()
107
-
108
- title_text="You are looking beautiful"
109
- tw,th=draw.textsize(title_text,font=title_font)
110
- draw.text(((W-tw)/2,10),title_text,fill="darkblue",font=title_font)
111
-
112
- margin=20
113
- max_w=W-2*margin
114
- words=chunk.split()
115
- line=""
116
- y=60
117
- for w in words:
118
- test=(line+" "+w).strip()
119
- if draw.textsize(test,font=font)[0]<=max_w: line=test
120
- else:
121
- draw.text((margin,y),line,fill="black",font=font)
122
- y+=22
123
- line=w
124
- if line: draw.text((margin,y),line,fill="black",font=font)
125
- img.save(slide_path)
126
-
127
- audio_path=os.path.join(tmp,f"audio_{i}.mp3")
128
- gTTS(text=chunk,lang=tts_lang).save(audio_path)
129
-
130
- duration=max(2,min(len(chunk)//12+3,8))
131
- clip=ImageClip(slide_path).set_duration(duration).set_audio(AudioFileClip(audio_path))
132
- clips.append(clip)
133
-
134
- if not clips: return None
135
- final=concatenate_videoclips(clips,method="compose")
136
- out=os.path.join(tmp,"output_video.mp4") if not preview else os.path.join(tmp,"preview_video.mp4")
137
- final.write_videofile(out,fps=24,codec="libx264",audio_codec="aac",verbose=False,logger=None)
138
- return out
139
- except:
140
  return None
141
 
142
- # =========================== #
143
- # Notes + Flowchart #
144
- # =========================== #
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
  def generate_notes_flowchart(text):
146
- if not text.strip(): return "No text provided.",None
147
- notes=call_groq(f"Summarize into concise study notes:\n\n{text}",max_tokens=500)
148
- img=Image.new("RGB",(480,320),(144,238,144))
149
- draw=ImageDraw.Draw(img)
150
- try: font = ImageFont.truetype("DejaVuSans.ttf",16)
151
- except: font=ImageFont.load_default()
152
-
153
- y=20
154
  for line in notes.split("\n"):
155
- if line.strip():
156
- draw.text((10,y),line.strip(),fill="black",font=font)
157
- y+=18
158
- if y>280: break
159
- return notes,img
160
-
161
- # =========================== #
162
- # Search Links #
163
- # =========================== #
164
- def get_youtube_link(q): return f"https://www.youtube.com/results?search_query={quote_plus(q)}"
165
- def get_google_link(q): return f"https://www.google.com/search?q={quote_plus(q)}"
166
-
167
- def get_links_clickable(topic):
168
- if not topic.strip(): return "No topic provided.",""
169
- yt_links=[f"[YouTube Result {i+1}]({get_youtube_link(topic)})" for i in range(3)]
170
- gg_links=[f"[Google Result {i+1}]({get_google_link(topic)})" for i in range(3)]
171
- return "\n".join(yt_links), "\n".join(gg_links)
172
-
173
- # =========================== #
174
- # Gradio Frontend #
175
- # =========================== #
176
- with gr.Blocks() as demo:
177
-
178
- gr.Markdown("## 🌟 Professional AI Assistant Demo (Hackathon)")
179
-
180
- with gr.Tab("Step 1: Sign Up"):
181
- su_name = gr.Textbox(label="Username")
182
- su_email = gr.Textbox(label="Email")
183
- su_pass = gr.Textbox(label="Password",type="password")
184
- su_contact = gr.Textbox(label="Contact Number")
185
- su_btn = gr.Button("Sign Up")
186
- su_msg = gr.Textbox(label="Message",interactive=False)
187
- su_code = gr.Textbox(label="Your verification code (demo)",interactive=False)
188
- su_btn.click(signup_user,inputs=[su_name,su_email,su_pass,su_contact],outputs=[su_msg,su_code])
189
-
190
- with gr.Tab("Step 2: Verify"):
191
- verify_email = gr.Textbox(label="Email")
192
- verify_code = gr.Textbox(label="Enter verification code")
193
- verify_btn = gr.Button("Verify")
194
- verify_msg = gr.Textbox(label="Verification Status",interactive=False)
195
- verify_btn.click(verify_user,inputs=[verify_email,verify_code],outputs=[verify_msg])
196
-
197
- with gr.Tab("Step 3: Login"):
198
- li_email = gr.Textbox(label="Email")
199
- li_pass = gr.Textbox(label="Password",type="password")
200
- li_btn = gr.Button("Login")
201
- li_msg = gr.Textbox(label="Login Status",interactive=False)
202
- li_success = gr.State(False)
203
-
204
- def login_wrapper(email,password):
205
- success,msg=login_user(email,password)
206
- return msg,success
207
-
208
- li_btn.click(login_wrapper,inputs=[li_email,li_pass],outputs=[li_msg,li_success])
209
-
210
- with gr.Tab("Step 4: Ask Question"):
211
- q_in = gr.Textbox(label="Type your question")
212
- ans_out = gr.Textbox(label="Answer",lines=12)
213
- mcq_out = gr.Textbox(label="MCQs",lines=12)
214
- preview_q_vid = gr.Video(label="Preview Video")
215
- full_q_vid = gr.Video(label="Full Video")
216
- q_btn = gr.Button("Get Answer")
217
-
218
- def process_question(q):
219
- ans = answer_text_query(q)
220
- mcq = generate_mcqs_from_text(ans)
221
- preview = create_video_simple(ans,preview=True)
222
- full = create_video_simple(ans,preview=False)
223
- return ans,mcq,preview,full
224
-
225
- q_btn.click(process_question,inputs=[q_in],outputs=[ans_out,mcq_out,preview_q_vid,full_q_vid])
226
-
227
- with gr.Tab("Step 5: Upload Document"):
228
- file_in = gr.File(label="Upload page image")
229
- sel = gr.CheckboxGroup(["Extracted Text","MCQs","Video","Notes & Flowchart"])
230
- lang = gr.Dropdown(label="Video language",choices=["en","ur","hi"],value="en")
231
- out_text = gr.Textbox(label="Extracted / Answer Text",lines=12)
232
- out_mcq = gr.Textbox(label="MCQs",lines=12)
233
- preview_vid = gr.Video(label="Preview Video")
234
- full_vid = gr.Video(label="Full Video")
235
- notes_out = gr.Textbox(label="Notes",lines=12)
236
- flowchart_out = gr.Image(label="Flowchart")
237
-
238
- def process_upload(file,outputs_selected,lang_code):
239
- text=""
240
- try: text=pytesseract.image_to_string(Image.open(file.name))
241
- except: text=""
242
-
243
- mcq_text=""
244
- preview_path=None
245
- video_path=None
246
- notes_text=""
247
- flowchart_img=None
248
-
249
- if "MCQs" in outputs_selected and text.strip():
250
- mcq_text=generate_mcqs_from_text(text)
251
-
252
- if "Video" in outputs_selected and text.strip():
253
- preview_path=create_video_simple(text,tts_lang=lang_code,preview=True)
254
- video_path=create_video_simple(text,tts_lang=lang_code,preview=False)
255
-
256
- if "Notes & Flowchart" in outputs_selected and text.strip():
257
- notes_text,flowchart_img=generate_notes_flowchart(text)
258
-
259
- return text or "",mcq_text or "",preview_path,video_path,notes_text,flowchart_img
260
 
261
- btn = gr.Button("Process")
262
- btn.click(process_upload,inputs=[file_in,sel,lang],
263
- outputs=[out_text,out_mcq,preview_vid,full_vid,notes_out,flowchart_out])
 
264
 
265
- with gr.Tab("Step 6: Links"):
266
- topic = gr.Textbox(label="Search topic")
267
- yt = gr.Markdown(label="YouTube links")
268
- gg = gr.Markdown(label="Google links")
269
- sbtn = gr.Button("Get Links")
270
- sbtn.click(get_links_clickable,inputs=[topic],outputs=[yt,gg])
271
 
272
- demo.launch(share=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import tempfile
3
+ import random
4
+ import requests
5
+ from urllib.parse import quote_plus
6
  from PIL import Image, ImageDraw, ImageFont
7
  import pytesseract
8
  from gtts import gTTS
9
  from moviepy.editor import ImageClip, AudioFileClip, concatenate_videoclips
10
  import gradio as gr
 
 
11
 
12
+ # ===========================
13
+ # Environment Variables
14
+ # ===========================
15
+ GROQ_API_KEY = os.getenv("GROQ_API_KEY", "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")
16
+ GROQ_MODEL = "llama-3.3-70b-versatile"
17
+
18
+ if not GROQ_API_KEY:
19
+ print("⚠️ WARNING: GROQ_API_KEY is missing. Add it in HuggingFace Secrets!")
20
+
21
+
22
+ # ===========================
23
+ # Users Database
24
+ # ===========================
25
  users_db = {}
26
  verification_codes = {}
27
 
28
+
29
+ # ===========================
30
+ # Authentication Functions
31
+ # ===========================
32
+ def signup_user(username, email, password, contact):
33
  if email in users_db:
34
+ return "Email already registered.", ""
35
+ code = str(random.randint(100000, 999999))
36
  verification_codes[email] = code
 
 
37
 
38
+ users_db[email] = {
39
+ "username": username,
40
+ "password": password,
41
+ "contact": contact,
42
+ "verified": False
43
+ }
44
+
45
+ return "Signup successful! Verification code:", code
46
+
47
+
48
+ def verify_user(email, code):
49
  if email not in users_db:
50
+ return "Email not registered."
51
  if users_db[email]["verified"]:
52
  return "Already verified."
53
+
54
  if verification_codes.get(email) == code:
55
  users_db[email]["verified"] = True
56
  verification_codes.pop(email)
57
+ return "Verification successful!"
58
  return "Invalid verification code."
59
 
60
+
61
+ def login_user(email, password):
62
  user = users_db.get(email)
63
+ if not user:
64
+ return False, "User not found."
65
+ if not user["verified"]:
66
+ return False, "Account not verified."
67
+ if user["password"] != password:
68
+ return False, "Incorrect password."
69
+ return True, f"Welcome {user['username']}!"
70
+
71
+
72
+ # ===========================
73
+ # Groq API Call
74
+ # ===========================
75
+ def call_groq(prompt, max_tokens=500):
76
+ if not GROQ_API_KEY:
77
+ return "❌ Missing GROQ_API_KEY in environment variables."
78
 
 
79
  url = "https://api.groq.com/openai/v1/chat/completions"
80
+ headers = {"Authorization": f"Bearer {GROQ_API_KEY}", "Content-Type": "application/json"}
81
+
82
  payload = {
83
+ "model": GROQ_MODEL,
84
+ "messages": [{"role": "user", "content": prompt}],
85
+ "max_tokens": max_tokens
86
  }
87
+
88
  try:
89
+ r = requests.post(url, json=payload, headers=headers, timeout=20)
90
  if r.status_code == 200:
91
+ return r.json()["choices"][0]["message"]["content"]
92
+ return f"API Error {r.status_code}: {r.text}"
93
  except Exception as e:
94
+ return f"API Exception: {e}"
95
 
96
+
97
+ # ===========================
98
+ # AI Helper Functions
99
+ # ===========================
100
+ def generate_mcqs_from_text(text, n=5):
101
+ prompt = f"Create {n} MCQs with 4 options and answers:\n\n{text}"
102
  return call_groq(prompt)
103
 
104
+
105
  def answer_text_query(query):
106
+ prompt = f"Answer clearly:\n\n{query}"
 
107
  return call_groq(prompt)
108
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
 
110
+ # ===========================
111
+ # Video Generator
112
+ # ===========================
113
+ def create_video_simple(text, tts_lang="en", preview=False):
114
+ if not text.strip():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  return None
116
 
117
+ tmp = tempfile.gettempdir()
118
+
119
+ lines = [l.strip() for l in text.split(".") if l.strip()]
120
+ if preview:
121
+ lines = lines[:1] # one slide preview
122
+
123
+ clips = []
124
+
125
+ for i, chunk in enumerate(lines):
126
+ slide_path = os.path.join(tmp, f"slide_{i}.png")
127
+
128
+ # Create slide
129
+ img = Image.new("RGB", (480, 320), (255, 182, 193))
130
+ draw = ImageDraw.Draw(img)
131
+ font = ImageFont.load_default()
132
+
133
+ draw.text((20, 20), "AI Generated Slide", fill="blue", font=font)
134
+ draw.text((20, 80), chunk[:220], fill="black", font=font)
135
+
136
+ img.save(slide_path)
137
+
138
+ # Audio
139
+ audio_path = os.path.join(tmp, f"audio_{i}.mp3")
140
+ gTTS(text=chunk, lang=tts_lang).save(audio_path)
141
+
142
+ # Clip
143
+ clip = ImageClip(slide_path).set_duration(4)
144
+ clip = clip.set_audio(AudioFileClip(audio_path))
145
+ clips.append(clip)
146
+
147
+ output_path = os.path.join(tmp, f"video_preview.mp4" if preview else "video_full.mp4")
148
+ video = concatenate_videoclips(clips)
149
+ video.write_videofile(output_path, fps=24, codec="libx264", audio_codec="aac")
150
+
151
+ return output_path
152
+
153
+
154
+ # ===========================
155
+ # Notes + Flowchart
156
+ # ===========================
157
  def generate_notes_flowchart(text):
158
+ notes = call_groq(f"Summarize into clean notes:\n\n{text}")
159
+ img = Image.new("RGB", (500, 350), (180, 250, 180))
160
+ draw = ImageDraw.Draw(img)
161
+ font = ImageFont.load_default()
162
+
163
+ y = 20
 
 
164
  for line in notes.split("\n"):
165
+ draw.text((10, y), line[:60], fill="black", font=font)
166
+ y += 18
167
+ if y > 300:
168
+ break
169
+ return notes, img
170
+
171
+
172
+ # ===========================
173
+ # Quick Search Links
174
+ # ===========================
175
+ def get_links(topic):
176
+ yt = f"https://www.youtube.com/results?search_query={quote_plus(topic)}"
177
+ gg = f"https://www.google.com/search?q={quote_plus(topic)}"
178
+ return yt, gg
179
+
180
+
181
+ # ===========================
182
+ # UI
183
+ # ===========================
184
+ with gr.Blocks(title="AI Study Wizard") as demo:
185
+
186
+ gr.Markdown("# 🎓 AI Study Wizard — Full Assistant")
187
+
188
+ # Signup
189
+ with gr.Tab("Sign Up"):
190
+ name = gr.Textbox(label="Name")
191
+ email = gr.Textbox(label="Email")
192
+ pwd = gr.Textbox(label="Password", type="password")
193
+ contact = gr.Textbox(label="Contact")
194
+ btn = gr.Button("Create Account")
195
+ msg = gr.Textbox(label="Message")
196
+ code_out = gr.Textbox(label="Verification Code (demo)")
197
+ btn.click(signup_user, [name, email, pwd, contact], [msg, code_out])
198
+
199
+ # Verify
200
+ with gr.Tab("Verify"):
201
+ v_email = gr.Textbox(label="Email")
202
+ v_code = gr.Textbox(label="Code")
203
+ v_btn = gr.Button("Verify")
204
+ v_msg = gr.Textbox(label="Status")
205
+ v_btn.click(verify_user, [v_email, v_code], v_msg)
206
+
207
+ # Login
208
+ with gr.Tab("Login"):
209
+ l_email = gr.Textbox(label="Email")
210
+ l_pass = gr.Textbox(label="Password", type="password")
211
+ l_btn = gr.Button("Login")
212
+ l_msg = gr.Textbox(label="Message")
213
+ l_btn.click(lambda e, p: login_user(e, p), [l_email, l_pass], l_msg)
214
+
215
+ # Ask Question
216
+ with gr.Tab("Ask AI"):
217
+ q = gr.Textbox(label="Your Question")
218
+ ans = gr.Textbox(label="Answer", lines=8)
219
+ mcq = gr.Textbox(label="MCQs", lines=8)
220
+ pv = gr.Video(label="Preview Video")
221
+ fv = gr.Video(label="Full Video")
222
+ b = gr.Button("Generate")
223
+
224
+ def process_query(q):
225
+ a = answer_text_query(q)
226
+ m = generate_mcqs_from_text(a)
227
+ prev = create_video_simple(a, preview=True)
228
+ full = create_video_simple(a, preview=False)
229
+ return a, m, prev, full
230
+
231
+ b.click(process_query, q, [ans, mcq, pv, fv])
232
+
233
+ # Upload Notes
234
+ with gr.Tab("Upload Image"):
235
+ file = gr.File(label="Upload Image")
236
+ lang = gr.Dropdown(["en", "ur", "hi"], value="en")
237
+ out_text = gr.Textbox(label="Extracted Text", lines=6)
238
+ out_mcq = gr.Textbox(label="MCQs", lines=6)
239
+ out_notes = gr.Textbox(label="Notes", lines=6)
240
+ out_flow = gr.Image(label="Flowchart")
241
+ out_prev = gr.Video(label="Preview Video")
242
+ out_full = gr.Video(label="Full Video")
243
+
244
+ def process_upload(f, language):
245
+ try:
246
+ text = pytesseract.image_to_string(Image.open(f.name))
247
+ except:
248
+ text = ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
249
 
250
+ mcqs = generate_mcqs_from_text(text) if text else ""
251
+ notes, img = generate_notes_flowchart(text) if text else ("", None)
252
+ prev = create_video_simple(text, tts_lang=language, preview=True) if text else None
253
+ full = create_video_simple(text, tts_lang=language, preview=False) if text else None
254
 
255
+ return text, mcqs, notes, img, prev, full
 
 
 
 
 
256
 
257
+ btn = gr.Button("Process")
258
+ btn.click(process_upload, [file, lang],
259
+ [out_text, out_mcq, out_notes, out_flow, out_prev, out_full])
260
+
261
+ # Search Links
262
+ with gr.Tab("Search"):
263
+ topic = gr.Textbox(label="Topic")
264
+ yt = gr.Textbox(label="YouTube", interactive=False)
265
+ gg = gr.Textbox(label="Google", interactive=False)
266
+ btn = gr.Button("Search")
267
+ btn.click(get_links, topic, [yt, gg])
268
+
269
+ demo.launch()