shukdevdatta123 commited on
Commit
13d28f0
Β·
verified Β·
1 Parent(s): 6e6cdfc

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +145 -95
app.py CHANGED
@@ -7,6 +7,7 @@ import json
7
  import time
8
  from typing import List, Dict, Any, Optional
9
  import spaces
 
10
 
11
  # Global variables to store API key and document text
12
  API_KEY = ""
@@ -17,13 +18,16 @@ def setup_client(api_key: str):
17
  """Initialize and test API key"""
18
  global API_KEY
19
  try:
20
- # Test the API key by creating a client and making a simple request
 
 
 
21
  client = OpenAI(
22
  base_url="https://openrouter.ai/api/v1",
23
- api_key=api_key,
24
  )
25
  # Store the API key globally
26
- API_KEY = api_key
27
  return "βœ… API Key configured successfully!"
28
  except Exception as e:
29
  return f"❌ Error configuring API: {str(e)}"
@@ -43,9 +47,15 @@ def extract_text_from_pdf(file_path: str) -> str:
43
  with open(file_path, 'rb') as file:
44
  pdf_reader = PyPDF2.PdfReader(file)
45
  text = ""
46
- for page in pdf_reader.pages:
47
- text += page.extract_text() + "\n"
48
- return text
 
 
 
 
 
 
49
  except Exception as e:
50
  return f"Error reading PDF: {str(e)}"
51
 
@@ -55,68 +65,101 @@ def extract_text_from_docx(file_path: str) -> str:
55
  doc = docx.Document(file_path)
56
  text = ""
57
  for paragraph in doc.paragraphs:
58
- text += paragraph.text + "\n"
59
- return text
 
 
 
 
 
 
 
 
 
60
  except Exception as e:
61
  return f"Error reading DOCX: {str(e)}"
62
 
63
- @spaces.GPU
64
  def process_document(file):
65
  """Process uploaded document and extract text"""
66
  global DOCUMENT_TEXT
67
 
 
 
68
  if file is None:
69
- DOCUMENT_TEXT = "" # Reset if no file
70
- return "❌ No file uploaded"
71
 
72
  try:
73
- file_path = file.name
 
 
 
 
 
 
 
 
74
  file_extension = file_path.lower().split('.')[-1]
 
75
 
 
76
  if file_extension == 'pdf':
77
  extracted_text = extract_text_from_pdf(file_path)
78
  elif file_extension in ['docx', 'doc']:
79
  extracted_text = extract_text_from_docx(file_path)
80
  else:
81
- DOCUMENT_TEXT = "" # Reset on unsupported format
82
- return "❌ Unsupported file format. Please upload PDF or DOCX files."
 
 
83
 
84
  # Check if extraction was successful
85
  if extracted_text.startswith("Error"):
86
- DOCUMENT_TEXT = "" # Reset on error
87
- return extracted_text
88
 
89
- # Set the global variable
90
  DOCUMENT_TEXT = extracted_text.strip()
91
 
92
- if DOCUMENT_TEXT and len(DOCUMENT_TEXT) > 0:
93
  word_count = len(DOCUMENT_TEXT.split())
94
- preview = DOCUMENT_TEXT[:200] + "..." if len(DOCUMENT_TEXT) > 200 else DOCUMENT_TEXT
95
- return f"βœ… Document processed successfully!\nπŸ“„ Word count: {word_count}\nπŸ“ Preview: {preview}"
 
 
 
 
 
 
96
  else:
97
- DOCUMENT_TEXT = "" # Reset if no text extracted
98
- return "❌ Could not extract text from the document. The document might be empty or contain only images."
99
 
100
  except Exception as e:
101
- DOCUMENT_TEXT = "" # Reset on any error
102
- return f"❌ Error processing document: {str(e)}"
 
 
103
 
104
- @spaces.GPU
105
  def generate_content(prompt: str, max_tokens: int = 2000) -> str:
106
  """Generate content using the AI model"""
107
- global DOCUMENT_TEXT
108
 
109
- if not API_KEY:
 
 
110
  return "❌ Please configure your API key first"
111
 
112
- if not DOCUMENT_TEXT or len(DOCUMENT_TEXT.strip()) == 0:
113
  return "❌ Please upload and process a document first. Make sure the document contains readable text."
114
 
115
  try:
116
  client = create_client()
117
  if not client:
118
  return "❌ Failed to create API client"
119
-
 
 
120
  completion = client.chat.completions.create(
121
  extra_headers={
122
  "HTTP-Referer": "https://educational-assistant.app",
@@ -130,16 +173,23 @@ def generate_content(prompt: str, max_tokens: int = 2000) -> str:
130
  },
131
  {
132
  "role": "user",
133
- "content": f"Document Content:\n{DOCUMENT_TEXT}\n\n{prompt}"
134
  }
135
  ],
136
  max_tokens=max_tokens,
137
  temperature=0.7
138
  )
139
- return completion.choices[0].message.content
 
 
 
 
140
  except Exception as e:
141
- return f"❌ Error generating content: {str(e)}"
 
 
142
 
 
143
  @spaces.GPU
144
  def generate_summary():
145
  """Generate comprehensive summary"""
@@ -378,15 +428,24 @@ def generate_practice_problems():
378
  """
379
  return generate_content(prompt, max_tokens=3500)
380
 
381
- def check_document_status():
382
- """Check if document is loaded"""
383
  global DOCUMENT_TEXT
384
- if DOCUMENT_TEXT and len(DOCUMENT_TEXT.strip()) > 0:
385
  word_count = len(DOCUMENT_TEXT.split())
386
- return f"βœ… Document loaded ({word_count} words)"
 
387
  else:
388
  return "❌ No document loaded"
389
 
 
 
 
 
 
 
 
 
390
  # Create Gradio interface
391
  def create_interface():
392
  with gr.Blocks(title="πŸ“š Educational Content Creator Assistant", theme=gr.themes.Soft()) as app:
@@ -405,21 +464,27 @@ def create_interface():
405
  api_key = gr.Textbox(
406
  label="OpenRouter API Key",
407
  type="password",
408
- placeholder="Enter your OpenRouter API key..."
 
409
  )
410
  setup_btn = gr.Button("πŸ”§ Configure API", variant="primary")
411
- setup_status = gr.Textbox(label="Status", interactive=False)
412
 
413
  gr.Markdown("### πŸ“„ Document Upload")
414
  file_upload = gr.File(
415
  label="Upload Document (PDF or DOCX)",
416
- file_types=[".pdf", ".docx", ".doc"]
 
417
  )
418
  process_btn = gr.Button("πŸ”„ Process Document", variant="secondary")
419
- process_status = gr.Textbox(label="Processing Status", interactive=False)
420
 
421
- # Add document status indicator
422
- doc_status = gr.Textbox(label="Document Status", value="❌ No document loaded", interactive=False)
 
 
 
 
423
 
424
  with gr.Column(scale=2):
425
  gr.Markdown("### 🎯 Generate Educational Content")
@@ -448,88 +513,70 @@ def create_interface():
448
 
449
  gr.Markdown("""
450
  ### πŸ“‹ How to Use:
451
- 1. **Get API Key:** Sign up at [OpenRouter](https://openrouter.ai/) and get your API key
452
- 2. **Configure:** Enter your API key and click "Configure API"
453
- 3. **Upload:** Upload a PDF or DOCX document
454
  4. **Process:** Click "Process Document" to extract text
455
  5. **Generate:** Choose any educational content type to generate
456
 
457
  ### 🎯 Content Types:
458
  - **Summary:** Comprehensive overview with key points
459
  - **Study Notes:** Structured notes with key concepts and memory aids
460
- - **Quiz:** Multiple choice, short answer, and essay questions
461
  - **Flashcards:** Question-answer pairs for memorization
462
  - **Mind Map:** Visual structure of document concepts
463
  - **Lesson Plan:** Complete teaching plan with objectives and activities
464
  - **Concept Explanations:** Deep dive into key concepts with examples
465
  - **Practice Problems:** Graded exercises from beginner to advanced
466
 
 
 
 
 
 
467
  ### ⚑ Performance Note:
468
  This app uses ZeroGPU for enhanced processing. Functions will automatically utilize GPU resources when needed.
469
  """)
470
 
471
  # Event handlers
 
 
 
 
 
472
  setup_btn.click(
473
- setup_client,
474
  inputs=[api_key],
475
- outputs=[setup_status]
476
  )
477
 
478
- def process_and_update_status(file):
479
- result = process_document(file)
480
- status = check_document_status()
481
- return result, status
482
 
483
  process_btn.click(
484
- process_and_update_status,
485
  inputs=[file_upload],
486
  outputs=[process_status, doc_status]
487
  )
488
 
489
- summary_btn.click(
490
- generate_summary,
491
- outputs=[output]
492
- )
493
-
494
- notes_btn.click(
495
- generate_study_notes,
496
- outputs=[output]
497
- )
498
-
499
- quiz_btn.click(
500
- generate_quiz,
501
- outputs=[output]
502
- )
503
-
504
- flashcards_btn.click(
505
- generate_flashcards,
506
- outputs=[output]
507
- )
508
-
509
- mindmap_btn.click(
510
- generate_mind_map,
511
- outputs=[output]
512
- )
513
 
514
- lesson_btn.click(
515
- generate_lesson_plan,
516
- outputs=[output]
517
- )
518
-
519
- concepts_btn.click(
520
- generate_concept_explanations,
521
- outputs=[output]
522
- )
523
-
524
- problems_btn.click(
525
- generate_practice_problems,
526
- outputs=[output]
527
- )
528
 
529
- # Update document status when page loads
530
  app.load(
531
- check_document_status,
532
- outputs=[doc_status]
533
  )
534
 
535
  return app
@@ -537,4 +584,7 @@ def create_interface():
537
  # Launch the application
538
  if __name__ == "__main__":
539
  app = create_interface()
540
- app.launch()
 
 
 
 
7
  import time
8
  from typing import List, Dict, Any, Optional
9
  import spaces
10
+ import os
11
 
12
  # Global variables to store API key and document text
13
  API_KEY = ""
 
18
  """Initialize and test API key"""
19
  global API_KEY
20
  try:
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:
33
  return f"❌ Error configuring API: {str(e)}"
 
47
  with open(file_path, 'rb') as file:
48
  pdf_reader = PyPDF2.PdfReader(file)
49
  text = ""
50
+ for page_num, page in enumerate(pdf_reader.pages):
51
+ try:
52
+ page_text = page.extract_text()
53
+ if page_text:
54
+ text += page_text + "\n"
55
+ except Exception as e:
56
+ print(f"Error extracting text from page {page_num}: {e}")
57
+ continue
58
+ return text.strip()
59
  except Exception as e:
60
  return f"Error reading PDF: {str(e)}"
61
 
 
65
  doc = docx.Document(file_path)
66
  text = ""
67
  for paragraph in doc.paragraphs:
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:
75
+ if cell.text.strip():
76
+ text += cell.text + "\n"
77
+
78
+ return text.strip()
79
  except Exception as e:
80
  return f"Error reading DOCX: {str(e)}"
81
 
 
82
  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']:
109
  extracted_text = extract_text_from_docx(file_path)
110
  else:
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",
 
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,
180
  temperature=0.7
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
+ return result
186
+
187
  except Exception as e:
188
+ error_msg = f"❌ Error generating content: {str(e)}"
189
+ print(f"API Error: {error_msg}") # Debug print
190
+ return error_msg
191
 
192
+ # Content generation functions with @spaces.GPU decorator
193
  @spaces.GPU
194
  def generate_summary():
195
  """Generate comprehensive summary"""
 
428
  """
429
  return generate_content(prompt, max_tokens=3500)
430
 
431
+ def get_document_status():
432
+ """Get current document status"""
433
  global DOCUMENT_TEXT
434
+ if DOCUMENT_TEXT and len(DOCUMENT_TEXT.strip()) > 10:
435
  word_count = len(DOCUMENT_TEXT.split())
436
+ char_count = len(DOCUMENT_TEXT)
437
+ return f"βœ… Document loaded ({word_count} words, {char_count} characters)"
438
  else:
439
  return "❌ No document loaded"
440
 
441
+ def get_api_status():
442
+ """Get current API status"""
443
+ global API_KEY
444
+ if API_KEY and API_KEY.strip():
445
+ return "βœ… API Key configured"
446
+ else:
447
+ return "❌ API Key not configured"
448
+
449
  # Create Gradio interface
450
  def create_interface():
451
  with gr.Blocks(title="πŸ“š Educational Content Creator Assistant", theme=gr.themes.Soft()) as app:
 
464
  api_key = gr.Textbox(
465
  label="OpenRouter API Key",
466
  type="password",
467
+ placeholder="Enter your OpenRouter API key...",
468
+ info="Get your API key from https://openrouter.ai/"
469
  )
470
  setup_btn = gr.Button("πŸ”§ Configure API", variant="primary")
471
+ setup_status = gr.Textbox(label="API Status", value=get_api_status(), interactive=False)
472
 
473
  gr.Markdown("### πŸ“„ Document Upload")
474
  file_upload = gr.File(
475
  label="Upload Document (PDF or DOCX)",
476
+ file_types=[".pdf", ".docx", ".doc"],
477
+ type="filepath"
478
  )
479
  process_btn = gr.Button("πŸ”„ Process Document", variant="secondary")
480
+ process_status = gr.Textbox(label="Processing Status", interactive=False, lines=4)
481
 
482
+ # Document status indicator
483
+ doc_status = gr.Textbox(
484
+ label="Document Status",
485
+ value=get_document_status(),
486
+ interactive=False
487
+ )
488
 
489
  with gr.Column(scale=2):
490
  gr.Markdown("### 🎯 Generate Educational Content")
 
513
 
514
  gr.Markdown("""
515
  ### πŸ“‹ How to Use:
516
+ 1. **Get API Key:** Sign up at [OpenRouter](https://openrouter.ai/) and get your free API key
517
+ 2. **Configure:** Enter your API key and click "Configure API"
518
+ 3. **Upload:** Upload a PDF or DOCX document (make sure it contains readable text)
519
  4. **Process:** Click "Process Document" to extract text
520
  5. **Generate:** Choose any educational content type to generate
521
 
522
  ### 🎯 Content Types:
523
  - **Summary:** Comprehensive overview with key points
524
  - **Study Notes:** Structured notes with key concepts and memory aids
525
+ - **Quiz:** Multiple choice, short answer, and essay questions with answers
526
  - **Flashcards:** Question-answer pairs for memorization
527
  - **Mind Map:** Visual structure of document concepts
528
  - **Lesson Plan:** Complete teaching plan with objectives and activities
529
  - **Concept Explanations:** Deep dive into key concepts with examples
530
  - **Practice Problems:** Graded exercises from beginner to advanced
531
 
532
+ ### πŸ’‘ Tips:
533
+ - Make sure your PDF contains selectable text (not just images)
534
+ - For best results, use documents with clear structure and headings
535
+ - The app works with academic papers, textbooks, reports, and study materials
536
+
537
  ### ⚑ Performance Note:
538
  This app uses ZeroGPU for enhanced processing. Functions will automatically utilize GPU resources when needed.
539
  """)
540
 
541
  # Event handlers
542
+ def setup_api_and_update_status(api_key):
543
+ result = setup_client(api_key)
544
+ status = get_api_status()
545
+ return result, status
546
+
547
  setup_btn.click(
548
+ setup_api_and_update_status,
549
  inputs=[api_key],
550
+ outputs=[setup_status, setup_status]
551
  )
552
 
553
+ def process_and_update_all_status(file):
554
+ process_result, doc_status_result = process_document(file)
555
+ return process_result, doc_status_result
 
556
 
557
  process_btn.click(
558
+ process_and_update_all_status,
559
  inputs=[file_upload],
560
  outputs=[process_status, doc_status]
561
  )
562
 
563
+ # Content generation button handlers
564
+ summary_btn.click(generate_summary, outputs=[output])
565
+ notes_btn.click(generate_study_notes, outputs=[output])
566
+ quiz_btn.click(generate_quiz, outputs=[output])
567
+ flashcards_btn.click(generate_flashcards, outputs=[output])
568
+ mindmap_btn.click(generate_mind_map, outputs=[output])
569
+ lesson_btn.click(generate_lesson_plan, outputs=[output])
570
+ concepts_btn.click(generate_concept_explanations, outputs=[output])
571
+ problems_btn.click(generate_practice_problems, outputs=[output])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
572
 
573
+ # Update status on app load
574
+ def update_initial_status():
575
+ return get_api_status(), get_document_status()
 
 
 
 
 
 
 
 
 
 
 
576
 
 
577
  app.load(
578
+ update_initial_status,
579
+ outputs=[setup_status, doc_status]
580
  )
581
 
582
  return app
 
584
  # Launch the application
585
  if __name__ == "__main__":
586
  app = create_interface()
587
+ app.launch(
588
+ debug=True,
589
+ share=False
590
+ )