shukdevdatta123 commited on
Commit
95e9fbc
Β·
verified Β·
1 Parent(s): 5e93724

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +58 -151
app.py CHANGED
@@ -21,12 +21,10 @@ def setup_client(api_key: str):
21
  if not api_key or api_key.strip() == "":
22
  return "❌ Please enter a valid API key"
23
 
24
- # Test the API key by creating a client
25
  client = OpenAI(
26
  base_url="https://openrouter.ai/api/v1",
27
  api_key=api_key.strip(),
28
  )
29
- # Store the API key globally
30
  API_KEY = api_key.strip()
31
  return "βœ… API Key configured successfully!"
32
  except Exception as e:
@@ -68,7 +66,6 @@ def extract_text_from_docx(file_path: str) -> str:
68
  if paragraph.text.strip():
69
  text += paragraph.text + "\n"
70
 
71
- # Also extract text from tables
72
  for table in doc.tables:
73
  for row in table.rows:
74
  for cell in row.cells:
@@ -83,26 +80,19 @@ def process_document(file):
83
  """Process uploaded document and extract text"""
84
  global DOCUMENT_TEXT
85
 
86
- print(f"Processing file: {file}") # Debug print
87
-
88
  if file is None:
89
  DOCUMENT_TEXT = ""
90
  return "❌ No file uploaded", "❌ No document loaded"
91
 
92
  try:
93
  file_path = file.name if hasattr(file, 'name') else str(file)
94
- print(f"File path: {file_path}") # Debug print
95
 
96
- # Check if file exists
97
  if not os.path.exists(file_path):
98
  DOCUMENT_TEXT = ""
99
  return "❌ File not found", "❌ No document loaded"
100
 
101
- # Get file extension
102
  file_extension = file_path.lower().split('.')[-1]
103
- print(f"File extension: {file_extension}") # Debug print
104
 
105
- # Extract text based on file type
106
  if file_extension == 'pdf':
107
  extracted_text = extract_text_from_pdf(file_path)
108
  elif file_extension in ['docx', 'doc']:
@@ -111,55 +101,43 @@ def process_document(file):
111
  DOCUMENT_TEXT = ""
112
  return "❌ Unsupported file format. Please upload PDF or DOCX files.", "❌ No document loaded"
113
 
114
- print(f"Extracted text length: {len(extracted_text) if extracted_text else 0}") # Debug print
115
-
116
- # Check if extraction was successful
117
  if extracted_text.startswith("Error"):
118
  DOCUMENT_TEXT = ""
119
  return extracted_text, "❌ No document loaded"
120
 
121
- # Clean and set the global variable
122
  DOCUMENT_TEXT = extracted_text.strip()
123
 
124
- if DOCUMENT_TEXT and len(DOCUMENT_TEXT) > 10: # Minimum length check
125
  word_count = len(DOCUMENT_TEXT.split())
126
  char_count = len(DOCUMENT_TEXT)
127
  preview = DOCUMENT_TEXT[:300] + "..." if len(DOCUMENT_TEXT) > 300 else DOCUMENT_TEXT
128
 
129
  status_msg = f"βœ… Document loaded ({word_count} words, {char_count} characters)"
130
  process_msg = f"βœ… Document processed successfully!\nπŸ“„ Word count: {word_count}\nπŸ“ Character count: {char_count}\n\nπŸ“– Preview:\n{preview}"
131
-
132
- print(f"Document processed successfully. Word count: {word_count}") # Debug print
133
  return process_msg, status_msg
134
  else:
135
  DOCUMENT_TEXT = ""
136
- return "❌ Could not extract meaningful text from the document. The document might be empty, contain only images, or be corrupted.", "❌ No document loaded"
137
 
138
  except Exception as e:
139
  DOCUMENT_TEXT = ""
140
- error_msg = f"❌ Error processing document: {str(e)}"
141
- print(f"Error: {error_msg}") # Debug print
142
- return error_msg, "❌ No document loaded"
143
 
144
  def generate_content(prompt: str, max_tokens: int = 2000) -> str:
145
  """Generate content using the AI model"""
146
  global DOCUMENT_TEXT, API_KEY
147
 
148
- print(f"Generate content called. API_KEY exists: {bool(API_KEY)}, DOCUMENT_TEXT length: {len(DOCUMENT_TEXT) if DOCUMENT_TEXT else 0}") # Debug print
149
-
150
  if not API_KEY or API_KEY.strip() == "":
151
  return "❌ Please configure your API key first"
152
 
153
  if not DOCUMENT_TEXT or len(DOCUMENT_TEXT.strip()) < 10:
154
- return "❌ Please upload and process a document first. Make sure the document contains readable text."
155
 
156
  try:
157
  client = create_client()
158
  if not client:
159
  return "❌ Failed to create API client"
160
 
161
- print("Sending request to API...") # Debug print
162
-
163
  completion = client.chat.completions.create(
164
  extra_headers={
165
  "HTTP-Referer": "https://educational-assistant.app",
@@ -169,11 +147,11 @@ def generate_content(prompt: str, max_tokens: int = 2000) -> str:
169
  messages=[
170
  {
171
  "role": "system",
172
- "content": "You are an expert educational content creator. Create comprehensive, engaging, and pedagogically sound educational materials based on the provided document content. Format your response using proper HTML tags for better presentation, but do not include <html>, <head>, <body>, or code block markers like ```html or ```. Start directly with the content using tags like <h1>, <h2>, <p>, etc."
173
  },
174
  {
175
  "role": "user",
176
- "content": f"Document Content:\n{DOCUMENT_TEXT[:4000]}\n\n{prompt}" # Limit document content to avoid token limits
177
  }
178
  ],
179
  max_tokens=max_tokens,
@@ -181,19 +159,14 @@ def generate_content(prompt: str, max_tokens: int = 2000) -> str:
181
  )
182
 
183
  result = completion.choices[0].message.content
184
- print(f"API response received. Length: {len(result) if result else 0}") # Debug print
185
-
186
- # Strip any unwanted code block markers if they sneak in
187
  result = result.replace("```html", "").replace("```", "").strip()
188
  return result
189
 
190
  except Exception as e:
191
- error_msg = f"❌ Error generating content: {str(e)}"
192
- print(f"API Error: {error_msg}") # Debug print
193
- return error_msg
194
 
195
  def create_download_file(content: str, filename: str) -> str:
196
- """Create downloadable HTML file"""
197
  html_template = f"""
198
  <!DOCTYPE html>
199
  <html lang="en">
@@ -222,48 +195,34 @@ def create_download_file(content: str, filename: str) -> str:
222
  margin-top: 30px;
223
  margin-bottom: 15px;
224
  }}
225
- .flashcard {{
226
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
227
- border-radius: 15px;
228
- padding: 20px;
229
- margin: 15px;
230
- box-shadow: 0 8px 25px rgba(0,0,0,0.15);
231
  cursor: pointer;
232
- transition: all 0.3s ease;
 
 
 
 
 
 
 
 
 
 
233
  color: white;
234
- position: relative;
235
- min-height: 150px;
236
  display: flex;
237
  flex-direction: column;
238
  justify-content: center;
239
- }}
240
- .flashcard:hover {{
241
- transform: translateY(-5px);
242
- box-shadow: 0 12px 35px rgba(0,0,0,0.25);
243
- }}
244
- .flashcard-front, .flashcard-back {{
245
  text-align: center;
246
  }}
247
- .flashcard-back {{
248
- display: none;
249
- }}
250
- .play-btn {{
251
- position: absolute;
252
- top: 10px;
253
- right: 15px;
254
- background: rgba(255,255,255,0.2);
255
- border: none;
256
- border-radius: 50%;
257
- width: 40px;
258
- height: 40px;
259
- font-size: 16px;
260
- color: white;
261
- cursor: pointer;
262
- transition: all 0.3s ease;
263
- }}
264
- .play-btn:hover {{
265
- background: rgba(255,255,255,0.3);
266
- transform: scale(1.1);
267
  }}
268
  .quiz-question {{
269
  background: #f8f9fa;
@@ -318,21 +277,10 @@ def create_download_file(content: str, filename: str) -> str:
318
  {content}
319
  </div>
320
  <script>
321
- function toggleCard(cardId) {{
322
- const front = document.getElementById(cardId + '-front');
323
- const back = document.getElementById(cardId + '-back');
324
- const btn = document.getElementById(cardId + '-btn');
325
-
326
- if (front && back && btn) {{
327
- if (front.style.display !== 'none') {{
328
- front.style.display = 'none';
329
- back.style.display = 'block';
330
- btn.innerHTML = 'πŸ”„';
331
- }} else {{
332
- front.style.display = 'block';
333
- back.style.display = 'none';
334
- btn.innerHTML = '▢️';
335
- }}
336
  }}
337
  }}
338
  </script>
@@ -340,14 +288,12 @@ def create_download_file(content: str, filename: str) -> str:
340
  </html>
341
  """
342
 
343
- # Save to temporary file
344
  temp_filename = f"temp_{filename}.html"
345
  with open(temp_filename, 'w', encoding='utf-8') as f:
346
  f.write(html_template)
347
 
348
  return temp_filename
349
 
350
- # Content generation functions with @spaces.GPU decorator
351
  @spaces.GPU
352
  def generate_summary():
353
  """Generate comprehensive summary"""
@@ -446,23 +392,24 @@ def generate_quiz():
446
 
447
  @spaces.GPU
448
  def generate_flashcards():
449
- """Generate interactive flashcards"""
450
  prompt = """Create 15-20 interactive flashcards based on this document. Do not include <html>, <head>, <body>, or code block markers. Start directly with the content.
451
 
452
  Format each flashcard using this exact HTML structure:
453
 
454
  <h1>🎴 Interactive Flashcards</h1>
455
- <p><em>Click the play button (▢️) on each card to reveal the answer!</em></p>
456
-
457
- <div class="flashcard" id="card1">
458
- <button class="play-btn" id="card1-btn" onclick="toggleCard('card1')">▢️</button>
459
- <div class="flashcard-front" id="card1-front" style="display: block;">
460
- <h3>Card 1</h3>
461
- <p><strong>[Question/Term]</strong></p>
462
- </div>
463
- <div class="flashcard-back" id="card1-back" style="display: none;">
464
- <h3>Answer</h3>
465
- <p>[Answer/Definition/Explanation]</p>
 
466
  </div>
467
  </div>
468
 
@@ -692,18 +639,14 @@ def get_api_status():
692
  else:
693
  return "❌ API Key not configured"
694
 
695
- # Create Gradio interface
696
  def create_interface():
697
  with gr.Blocks(title="πŸ“š Educational Content Creator Assistant", theme=gr.themes.Soft()) as app:
698
  gr.Markdown("""
699
  # πŸ“š Educational Content Creator Assistant
700
- Transform your documents into comprehensive educational materials using AI with interactive features!
701
 
702
- **New Features:**
703
- - 🎴 Interactive Flashcards with Play Buttons
704
- - πŸ“„ HTML Formatted Responses
705
- - πŸ’Ύ Download All Content as HTML Files
706
- - πŸ–¨οΈ Print-Ready Formats
707
 
708
  *Powered by ZeroGPU for enhanced performance*
709
  """)
@@ -729,7 +672,6 @@ def create_interface():
729
  process_btn = gr.Button("πŸ”„ Process Document", variant="secondary")
730
  process_status = gr.Textbox(label="Processing Status", interactive=False, lines=4)
731
 
732
- # Document status indicator
733
  doc_status = gr.Textbox(
734
  label="Document Status",
735
  value=get_document_status(),
@@ -753,58 +695,32 @@ def create_interface():
753
  concepts_btn = gr.Button("πŸ” Concept Explanations", variant="secondary")
754
  problems_btn = gr.Button("πŸ’ͺ Practice Problems", variant="secondary")
755
 
756
- # HTML output with download capability
757
  output = gr.HTML(
758
- label="Generated Content (Interactive)",
759
- value="<p>Generated educational content will appear here with interactive features...</p>"
760
  )
761
 
762
- # Download buttons
763
  with gr.Row():
764
  download_file = gr.File(label="πŸ“₯ Download Content", visible=False)
765
  download_btn = gr.Button("πŸ’Ύ Prepare Download", variant="secondary", visible=False)
766
 
767
  gr.Markdown("""
768
  ### πŸ“‹ How to Use:
769
- 1. **Get API Key:** Sign up at [OpenRouter](https://openrouter.ai/) and get your free API key
770
  2. **Configure:** Enter your API key and click "Configure API"
771
- 3. **Upload:** Upload a PDF or DOCX document (make sure it contains readable text)
772
  4. **Process:** Click "Process Document" to extract text
773
- 5. **Generate:** Choose any educational content type to generate interactive HTML content
774
- 6. **Download:** Use the "Prepare Download" button to get an HTML file with all content
775
-
776
- ### 🎯 Enhanced Content Types:
777
- - **πŸ“‹ Summary:** Comprehensive overview with styled HTML sections
778
- - **πŸ“– Study Notes:** Structured notes with highlighted key concepts
779
- - **πŸ“ Quiz:** Interactive quiz with styled questions and answer keys
780
- - **🎴 Interactive Flashcards:** Click-to-flip cards with play buttons!
781
- - **🧠 Mind Map:** Visual structure with styled branches
782
- - **πŸ“š Lesson Plan:** Complete teaching plan with time management
783
- - **πŸ” Concept Explanations:** Deep dive with styled concept boxes
784
- - **πŸ’ͺ Practice Problems:** Graded exercises with solution reveals
785
-
786
- ### ✨ New Interactive Features:
787
- - **🎴 Flashcards:** Click the play button (▢️) to flip cards and see answers
788
- - **πŸ“„ HTML Formatting:** All content now uses proper HTML styling
789
- - **πŸ’Ύ Download:** Get complete HTML files with embedded CSS and JavaScript
790
- - **πŸ–¨οΈ Print Ready:** Downloaded files include print-optimized styling
791
 
792
  ### πŸ’‘ Tips:
793
- - Make sure your PDF contains selectable text (not just images)
794
- - For best results, use documents with clear structure and headings
795
- - The app works with academic papers, textbooks, reports, and study materials
796
- - Interactive flashcards work best when viewed in the downloaded HTML file
797
- - Downloaded files can be opened in any web browser for offline use
798
-
799
- ### ⚑ Performance Note:
800
- This app uses ZeroGPU for enhanced processing. Functions will automatically utilize GPU resources when needed.
801
  """)
802
 
803
- # Store the last generated content for download
804
  last_content = gr.State("")
805
  last_content_type = gr.State("")
806
 
807
- # Event handlers
808
  def setup_api_and_update_status(api_key):
809
  result = setup_client(api_key)
810
  status = get_api_status()
@@ -826,7 +742,6 @@ def create_interface():
826
  outputs=[process_status, doc_status]
827
  )
828
 
829
- # Enhanced content generation functions that return HTML and enable download
830
  def generate_and_display_summary():
831
  content = generate_summary()
832
  return content, content, "summary", gr.update(visible=True)
@@ -859,17 +774,12 @@ def create_interface():
859
  content = generate_practice_problems()
860
  return content, content, "practice_problems", gr.update(visible=True)
861
 
862
- # Download preparation function
863
  def prepare_download(content, content_type):
864
  if not content or content.startswith("❌"):
865
  return None
866
-
867
- # Create downloadable file
868
- filename = f"educational_content_{content_type}"
869
- temp_file = create_download_file(content, filename)
870
  return temp_file
871
 
872
- # Content generation button handlers with download capability
873
  summary_btn.click(
874
  generate_and_display_summary,
875
  outputs=[output, last_content, last_content_type, download_btn]
@@ -910,7 +820,6 @@ def create_interface():
910
  outputs=[output, last_content, last_content_type, download_btn]
911
  )
912
 
913
- # Download button handler
914
  def handle_download(content, content_type):
915
  if content and not content.startswith("❌"):
916
  temp_file = prepare_download(content, content_type)
@@ -923,7 +832,6 @@ def create_interface():
923
  outputs=[download_file, download_file]
924
  )
925
 
926
- # Update status on app load
927
  def update_initial_status():
928
  return get_api_status(), get_document_status()
929
 
@@ -934,7 +842,6 @@ def create_interface():
934
 
935
  return app
936
 
937
- # Launch the application
938
  if __name__ == "__main__":
939
  app = create_interface()
940
  app.launch(
 
21
  if not api_key or api_key.strip() == "":
22
  return "❌ Please enter a valid API key"
23
 
 
24
  client = OpenAI(
25
  base_url="https://openrouter.ai/api/v1",
26
  api_key=api_key.strip(),
27
  )
 
28
  API_KEY = api_key.strip()
29
  return "βœ… API Key configured successfully!"
30
  except Exception as e:
 
66
  if paragraph.text.strip():
67
  text += paragraph.text + "\n"
68
 
 
69
  for table in doc.tables:
70
  for row in table.rows:
71
  for cell in row.cells:
 
80
  """Process uploaded document and extract text"""
81
  global DOCUMENT_TEXT
82
 
 
 
83
  if file is None:
84
  DOCUMENT_TEXT = ""
85
  return "❌ No file uploaded", "❌ No document loaded"
86
 
87
  try:
88
  file_path = file.name if hasattr(file, 'name') else str(file)
 
89
 
 
90
  if not os.path.exists(file_path):
91
  DOCUMENT_TEXT = ""
92
  return "❌ File not found", "❌ No document loaded"
93
 
 
94
  file_extension = file_path.lower().split('.')[-1]
 
95
 
 
96
  if file_extension == 'pdf':
97
  extracted_text = extract_text_from_pdf(file_path)
98
  elif file_extension in ['docx', 'doc']:
 
101
  DOCUMENT_TEXT = ""
102
  return "❌ Unsupported file format. Please upload PDF or DOCX files.", "❌ No document loaded"
103
 
 
 
 
104
  if extracted_text.startswith("Error"):
105
  DOCUMENT_TEXT = ""
106
  return extracted_text, "❌ No document loaded"
107
 
 
108
  DOCUMENT_TEXT = extracted_text.strip()
109
 
110
+ if DOCUMENT_TEXT and len(DOCUMENT_TEXT) > 10:
111
  word_count = len(DOCUMENT_TEXT.split())
112
  char_count = len(DOCUMENT_TEXT)
113
  preview = DOCUMENT_TEXT[:300] + "..." if len(DOCUMENT_TEXT) > 300 else DOCUMENT_TEXT
114
 
115
  status_msg = f"βœ… Document loaded ({word_count} words, {char_count} characters)"
116
  process_msg = f"βœ… Document processed successfully!\nπŸ“„ Word count: {word_count}\nπŸ“ Character count: {char_count}\n\nπŸ“– Preview:\n{preview}"
 
 
117
  return process_msg, status_msg
118
  else:
119
  DOCUMENT_TEXT = ""
120
+ return "❌ Could not extract meaningful text from the document.", "❌ No document loaded"
121
 
122
  except Exception as e:
123
  DOCUMENT_TEXT = ""
124
+ return f"❌ Error processing document: {str(e)}", "❌ No document loaded"
 
 
125
 
126
  def generate_content(prompt: str, max_tokens: int = 2000) -> str:
127
  """Generate content using the AI model"""
128
  global DOCUMENT_TEXT, API_KEY
129
 
 
 
130
  if not API_KEY or API_KEY.strip() == "":
131
  return "❌ Please configure your API key first"
132
 
133
  if not DOCUMENT_TEXT or len(DOCUMENT_TEXT.strip()) < 10:
134
+ return "❌ Please upload and process a document first."
135
 
136
  try:
137
  client = create_client()
138
  if not client:
139
  return "❌ Failed to create API client"
140
 
 
 
141
  completion = client.chat.completions.create(
142
  extra_headers={
143
  "HTTP-Referer": "https://educational-assistant.app",
 
147
  messages=[
148
  {
149
  "role": "system",
150
+ "content": "You are an expert educational content creator. Create engaging educational materials based on the provided document content. Format your response using proper HTML tags, but do not include <html>, <head>, <body>, or code block markers. Start directly with the content using tags like <h1>, <h2>, <p>, etc."
151
  },
152
  {
153
  "role": "user",
154
+ "content": f"Document Content:\n{DOCUMENT_TEXT[:4000]}\n\n{prompt}"
155
  }
156
  ],
157
  max_tokens=max_tokens,
 
159
  )
160
 
161
  result = completion.choices[0].message.content
 
 
 
162
  result = result.replace("```html", "").replace("```", "").strip()
163
  return result
164
 
165
  except Exception as e:
166
+ return f"❌ Error generating content: {str(e)}"
 
 
167
 
168
  def create_download_file(content: str, filename: str) -> str:
169
+ """Create downloadable HTML file with full structure and interactivity"""
170
  html_template = f"""
171
  <!DOCTYPE html>
172
  <html lang="en">
 
195
  margin-top: 30px;
196
  margin-bottom: 15px;
197
  }}
198
+ .flashcard-slider {{
199
+ width: 100%;
200
+ max-width: 400px;
201
+ margin: 20px auto;
202
+ overflow: hidden;
203
+ position: relative;
204
  cursor: pointer;
205
+ }}
206
+ .slides {{
207
+ display: flex;
208
+ width: 200%;
209
+ transition: transform 0.3s ease;
210
+ }}
211
+ .slide {{
212
+ width: 50%;
213
+ box-sizing: border-box;
214
+ padding: 30px;
215
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
216
  color: white;
217
+ border-radius: 15px;
218
+ min-height: 200px;
219
  display: flex;
220
  flex-direction: column;
221
  justify-content: center;
 
 
 
 
 
 
222
  text-align: center;
223
  }}
224
+ .showing-answer .slides {{
225
+ transform: translateX(-50%);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
226
  }}
227
  .quiz-question {{
228
  background: #f8f9fa;
 
277
  {content}
278
  </div>
279
  <script>
280
+ function toggleFlashcard(id) {{
281
+ const flashcard = document.getElementById(id);
282
+ if (flashcard) {{
283
+ flashcard.classList.toggle('showing-answer');
 
 
 
 
 
 
 
 
 
 
 
284
  }}
285
  }}
286
  </script>
 
288
  </html>
289
  """
290
 
 
291
  temp_filename = f"temp_{filename}.html"
292
  with open(temp_filename, 'w', encoding='utf-8') as f:
293
  f.write(html_template)
294
 
295
  return temp_filename
296
 
 
297
  @spaces.GPU
298
  def generate_summary():
299
  """Generate comprehensive summary"""
 
392
 
393
  @spaces.GPU
394
  def generate_flashcards():
395
+ """Generate interactive flashcards with slider functionality"""
396
  prompt = """Create 15-20 interactive flashcards based on this document. Do not include <html>, <head>, <body>, or code block markers. Start directly with the content.
397
 
398
  Format each flashcard using this exact HTML structure:
399
 
400
  <h1>🎴 Interactive Flashcards</h1>
401
+ <p><em>Click on a card to slide between question and answer!</em></p>
402
+
403
+ <div class="flashcard-slider" id="card1" onclick="toggleFlashcard('card1')">
404
+ <div class="slides">
405
+ <div class="slide question">
406
+ <h3>Card 1</h3>
407
+ <p><strong>[Question/Term]</strong></p>
408
+ </div>
409
+ <div class="slide answer">
410
+ <h3>Answer</h3>
411
+ <p>[Answer/Definition/Explanation]</p>
412
+ </div>
413
  </div>
414
  </div>
415
 
 
639
  else:
640
  return "❌ API Key not configured"
641
 
 
642
  def create_interface():
643
  with gr.Blocks(title="πŸ“š Educational Content Creator Assistant", theme=gr.themes.Soft()) as app:
644
  gr.Markdown("""
645
  # πŸ“š Educational Content Creator Assistant
646
+ Transform your documents into comprehensive educational materials using AI!
647
 
648
+ **New Feature:**
649
+ - 🎴 Interactive Flashcards now work like an image sliderβ€”click to slide between question and answer!
 
 
 
650
 
651
  *Powered by ZeroGPU for enhanced performance*
652
  """)
 
672
  process_btn = gr.Button("πŸ”„ Process Document", variant="secondary")
673
  process_status = gr.Textbox(label="Processing Status", interactive=False, lines=4)
674
 
 
675
  doc_status = gr.Textbox(
676
  label="Document Status",
677
  value=get_document_status(),
 
695
  concepts_btn = gr.Button("πŸ” Concept Explanations", variant="secondary")
696
  problems_btn = gr.Button("πŸ’ͺ Practice Problems", variant="secondary")
697
 
 
698
  output = gr.HTML(
699
+ label="Generated Content",
700
+ value="<p>Generated content will appear here...</p>"
701
  )
702
 
 
703
  with gr.Row():
704
  download_file = gr.File(label="πŸ“₯ Download Content", visible=False)
705
  download_btn = gr.Button("πŸ’Ύ Prepare Download", variant="secondary", visible=False)
706
 
707
  gr.Markdown("""
708
  ### πŸ“‹ How to Use:
709
+ 1. **Get API Key:** Sign up at [OpenRouter](https://openrouter.ai/)
710
  2. **Configure:** Enter your API key and click "Configure API"
711
+ 3. **Upload:** Upload a PDF or DOCX document
712
  4. **Process:** Click "Process Document" to extract text
713
+ 5. **Generate:** Choose a content type to generate
714
+ 6. **Download:** Download the HTML file to see interactive flashcards
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
715
 
716
  ### πŸ’‘ Tips:
717
+ - Flashcards slide between question and answer when clicked (in the downloaded file).
718
+ - Use the downloaded HTML file in a browser for full interactivity.
 
 
 
 
 
 
719
  """)
720
 
 
721
  last_content = gr.State("")
722
  last_content_type = gr.State("")
723
 
 
724
  def setup_api_and_update_status(api_key):
725
  result = setup_client(api_key)
726
  status = get_api_status()
 
742
  outputs=[process_status, doc_status]
743
  )
744
 
 
745
  def generate_and_display_summary():
746
  content = generate_summary()
747
  return content, content, "summary", gr.update(visible=True)
 
774
  content = generate_practice_problems()
775
  return content, content, "practice_problems", gr.update(visible=True)
776
 
 
777
  def prepare_download(content, content_type):
778
  if not content or content.startswith("❌"):
779
  return None
780
+ temp_file = create_download_file(content, content_type)
 
 
 
781
  return temp_file
782
 
 
783
  summary_btn.click(
784
  generate_and_display_summary,
785
  outputs=[output, last_content, last_content_type, download_btn]
 
820
  outputs=[output, last_content, last_content_type, download_btn]
821
  )
822
 
 
823
  def handle_download(content, content_type):
824
  if content and not content.startswith("❌"):
825
  temp_file = prepare_download(content, content_type)
 
832
  outputs=[download_file, download_file]
833
  )
834
 
 
835
  def update_initial_status():
836
  return get_api_status(), get_document_status()
837
 
 
842
 
843
  return app
844
 
 
845
  if __name__ == "__main__":
846
  app = create_interface()
847
  app.launch(