Dannyar608 commited on
Commit
db322cc
·
verified ·
1 Parent(s): f965c35

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +120 -82
app.py CHANGED
@@ -28,38 +28,75 @@ MAX_AGE = 120
28
  SESSION_TOKEN_LENGTH = 32
29
  HF_TOKEN = os.getenv("HF_TOKEN")
30
 
 
 
 
 
 
 
 
 
31
  # Initialize Hugging Face API
32
  if HF_TOKEN:
33
  hf_api = HfApi(token=HF_TOKEN)
34
  HfFolder.save_token(HF_TOKEN)
35
 
36
- # ========== DEEPSEEK MODEL LOADING ==========
37
- def load_deepseek_model():
38
- """Load the DeepSeek model with progress tracking"""
39
- try:
40
- start_time = time.time()
41
- tokenizer = AutoTokenizer.from_pretrained(
42
- "deepseek-ai/DeepSeek-V3",
43
- trust_remote_code=True
44
- )
45
-
46
- model = AutoModelForCausalLM.from_pretrained(
47
- "deepseek-ai/DeepSeek-V3",
48
- trust_remote_code=True,
49
- torch_dtype=torch.float16,
50
- device_map="auto" if torch.cuda.is_available() else None
51
- )
52
-
53
- load_time = time.time() - start_time
54
- print(f"DeepSeek model loaded in {load_time:.2f} seconds")
55
- return model, tokenizer
56
-
57
- except Exception as e:
58
- print(f"Error loading DeepSeek model: {str(e)}")
59
- return None, None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
 
61
- # Load model at startup
62
- model, tokenizer = load_deepseek_model()
63
 
64
  # ========== UTILITY FUNCTIONS ==========
65
  def generate_session_token() -> str:
@@ -198,13 +235,14 @@ def remove_sensitive_info(text: str) -> str:
198
  return text
199
 
200
  # ========== TRANSCRIPT PARSING ==========
201
- def parse_transcript_with_deepseek(text: str) -> Dict:
202
- """Use local DeepSeek model to parse transcript text"""
 
203
  if model is None or tokenizer is None:
204
- raise gr.Error("DeepSeek model failed to load. Please try again later.")
205
 
206
  # Pre-process the text
207
- text = remove_sensitive_info(text[:15000]) # Limit to first 15k chars
208
 
209
  prompt = f"""
210
  Analyze this academic transcript and extract structured information:
@@ -218,57 +256,41 @@ def parse_transcript_with_deepseek(text: str) -> Dict:
218
  * Credits earned
219
  * Year/semester taken
220
  * Grade level when taken
221
- Return the data in this JSON structure:
222
- {{
223
- "grade_level": "11",
224
- "gpa": {{
225
- "weighted": "4.2",
226
- "unweighted": "3.9"
227
- }},
228
- "courses": [
229
- {{
230
- "code": "MATH101",
231
- "name": "Algebra II",
232
- "grade": "A",
233
- "credits": "1.0",
234
- "year": "2023-2024",
235
- "grade_level": "11"
236
- }}
237
- ]
238
- }}
239
  Transcript Text:
240
  {text}
241
  """
242
 
243
  try:
 
 
244
  # Tokenize and generate response
245
  inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
 
246
 
247
  outputs = model.generate(
248
  **inputs,
249
- max_new_tokens=2000,
250
  temperature=0.1,
251
  do_sample=True
252
  )
 
253
 
254
  # Decode the response
255
  response = tokenizer.decode(outputs[0], skip_special_tokens=True)
256
 
257
- # Extract the JSON content from the response
258
- if '```json' in response:
259
- json_str = response.split('```json')[1].split('```')[0].strip()
260
- elif '```' in response:
261
- json_str = response.split('```')[1].split('```')[0].strip()
262
- else:
263
- json_str = response
264
 
265
- # Parse and validate the JSON
266
  parsed_data = json.loads(json_str)
 
267
 
268
  return validate_parsed_data(parsed_data)
269
 
270
  except torch.cuda.OutOfMemoryError:
271
- raise gr.Error("The model ran out of memory. Try with a smaller transcript or upgrade your GPU.")
272
  except Exception as e:
273
  raise gr.Error(f"Error processing transcript: {str(e)}")
274
 
@@ -333,7 +355,7 @@ def format_transcript_output(data: Dict) -> str:
333
 
334
  return '\n'.join(output)
335
 
336
- def parse_transcript(file_obj) -> Tuple[str, Optional[Dict]]:
337
  """Main function to parse transcript files."""
338
  try:
339
  if not file_obj:
@@ -345,8 +367,8 @@ def parse_transcript(file_obj) -> Tuple[str, Optional[Dict]]:
345
  # Extract text from file
346
  text = extract_text_from_file(file_obj.name, file_ext)
347
 
348
- # Use DeepSeek for parsing
349
- parsed_data = parse_transcript_with_deepseek(text)
350
 
351
  # Format output text
352
  output_text = format_transcript_output(parsed_data)
@@ -1069,6 +1091,12 @@ def create_interface():
1069
  background-color: #fff3e0;
1070
  color: #e65100;
1071
  }
 
 
 
 
 
 
1072
  """
1073
 
1074
  gr.Markdown("""
@@ -1077,13 +1105,21 @@ def create_interface():
1077
  Complete each step to get customized learning recommendations.
1078
  """)
1079
 
1080
- # Model loading status
1081
- model_status = gr.HTML(
1082
- value="<div class='model-loading'>Loading AI model... (This may take a few minutes)</div>" if model is None else "",
1083
- visible=model is None
1084
- )
1085
-
1086
- # Progress tracker - now with dynamic styling
 
 
 
 
 
 
 
 
1087
  with gr.Row():
1088
  with gr.Column(scale=1):
1089
  step1 = gr.Button("1. Upload Transcript", elem_classes="incomplete-tab")
@@ -1132,11 +1168,8 @@ def create_interface():
1132
  )
1133
  transcript_data = gr.State()
1134
 
1135
- def process_transcript_and_update(file_obj, current_tab_status):
1136
- if model is None:
1137
- return "Error: AI model failed to load. Please try again later.", None, current_tab_status, gr.update(), gr.update(), gr.update()
1138
-
1139
- output_text, data = parse_transcript(file_obj)
1140
  if "Error" not in output_text:
1141
  new_status = current_tab_status.copy()
1142
  new_status[0] = True
@@ -1454,15 +1487,20 @@ def create_interface():
1454
  outputs=[tabs, nav_message, quiz_alert]
1455
  )
1456
 
1457
- # Check model loading status
1458
- def check_model_status():
1459
- if model is not None and tokenizer is not None:
1460
- return gr.update(visible=False)
1461
- return gr.update(visible=True)
 
 
 
 
 
1462
 
1463
- app.load(
1464
- fn=check_model_status,
1465
- inputs=None,
1466
  outputs=model_status
1467
  )
1468
 
@@ -1474,4 +1512,4 @@ app = create_interface()
1474
  # For Hugging Face Spaces deployment
1475
  if __name__ == "__main__":
1476
  app.launch()
1477
-
 
28
  SESSION_TOKEN_LENGTH = 32
29
  HF_TOKEN = os.getenv("HF_TOKEN")
30
 
31
+ # Model configuration
32
+ MODEL_CHOICES = {
33
+ "TinyLlama (Fastest)": "TinyLlama/TinyLlama-1.1B-Chat-v1.0",
34
+ "Phi-2 (Balanced)": "microsoft/phi-2",
35
+ "DeepSeek-V3 (Most Powerful)": "deepseek-ai/DeepSeek-V3"
36
+ }
37
+ DEFAULT_MODEL = "TinyLlama (Fastest)"
38
+
39
  # Initialize Hugging Face API
40
  if HF_TOKEN:
41
  hf_api = HfApi(token=HF_TOKEN)
42
  HfFolder.save_token(HF_TOKEN)
43
 
44
+ # ========== OPTIMIZED MODEL LOADING ==========
45
+ class ModelLoader:
46
+ def __init__(self):
47
+ self.model = None
48
+ self.tokenizer = None
49
+ self.loaded = False
50
+ self.loading = False
51
+ self.error = None
52
+ self.current_model = None
53
+
54
+ def load_model(self, model_name, progress=gr.Progress()):
55
+ """Lazy load the model with progress feedback"""
56
+ if self.loaded and self.current_model == model_name:
57
+ return self.model, self.tokenizer
58
+
59
+ self.loading = True
60
+ self.error = None
61
+ try:
62
+ progress(0, desc=f"Loading {model_name}...")
63
+
64
+ # Clear previous model if any
65
+ if self.model:
66
+ del self.model
67
+ del self.tokenizer
68
+ torch.cuda.empty_cache()
69
+
70
+ # Load tokenizer first
71
+ self.tokenizer = AutoTokenizer.from_pretrained(
72
+ MODEL_CHOICES[model_name],
73
+ trust_remote_code=True
74
+ )
75
+ progress(0.3, desc="Loaded tokenizer...")
76
+
77
+ # Load model with appropriate settings
78
+ self.model = AutoModelForCausalLM.from_pretrained(
79
+ MODEL_CHOICES[model_name],
80
+ trust_remote_code=True,
81
+ torch_dtype=torch.float16,
82
+ device_map="auto" if torch.cuda.is_available() else None,
83
+ low_cpu_mem_usage=True
84
+ )
85
+
86
+ progress(0.9, desc="Finalizing...")
87
+ self.loaded = True
88
+ self.current_model = model_name
89
+ return self.model, self.tokenizer
90
+
91
+ except Exception as e:
92
+ self.error = str(e)
93
+ print(f"Error loading model: {self.error}")
94
+ return None, None
95
+ finally:
96
+ self.loading = False
97
 
98
+ # Initialize model loader
99
+ model_loader = ModelLoader()
100
 
101
  # ========== UTILITY FUNCTIONS ==========
102
  def generate_session_token() -> str:
 
235
  return text
236
 
237
  # ========== TRANSCRIPT PARSING ==========
238
+ def parse_transcript_with_ai(text: str, progress=gr.Progress()) -> Dict:
239
+ """Use AI model to parse transcript text with progress feedback"""
240
+ model, tokenizer = model_loader.load_model(model_loader.current_model or DEFAULT_MODEL, progress)
241
  if model is None or tokenizer is None:
242
+ raise gr.Error(f"Model failed to load. {model_loader.error or 'Please try loading a model first.'}")
243
 
244
  # Pre-process the text
245
+ text = remove_sensitive_info(text[:15000]) # Limit input size
246
 
247
  prompt = f"""
248
  Analyze this academic transcript and extract structured information:
 
256
  * Credits earned
257
  * Year/semester taken
258
  * Grade level when taken
259
+ Return the data in JSON format.
260
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
261
  Transcript Text:
262
  {text}
263
  """
264
 
265
  try:
266
+ progress(0.1, desc="Processing transcript...")
267
+
268
  # Tokenize and generate response
269
  inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
270
+ progress(0.4)
271
 
272
  outputs = model.generate(
273
  **inputs,
274
+ max_new_tokens=1500, # Reduced from original
275
  temperature=0.1,
276
  do_sample=True
277
  )
278
+ progress(0.8)
279
 
280
  # Decode the response
281
  response = tokenizer.decode(outputs[0], skip_special_tokens=True)
282
 
283
+ # Extract JSON from response
284
+ json_str = response.split('```json')[1].split('```')[0].strip() if '```json' in response else response
 
 
 
 
 
285
 
286
+ # Parse and validate
287
  parsed_data = json.loads(json_str)
288
+ progress(1.0)
289
 
290
  return validate_parsed_data(parsed_data)
291
 
292
  except torch.cuda.OutOfMemoryError:
293
+ raise gr.Error("The model ran out of memory. Try with a smaller transcript or use a smaller model.")
294
  except Exception as e:
295
  raise gr.Error(f"Error processing transcript: {str(e)}")
296
 
 
355
 
356
  return '\n'.join(output)
357
 
358
+ def parse_transcript(file_obj, progress=gr.Progress()) -> Tuple[str, Optional[Dict]]:
359
  """Main function to parse transcript files."""
360
  try:
361
  if not file_obj:
 
367
  # Extract text from file
368
  text = extract_text_from_file(file_obj.name, file_ext)
369
 
370
+ # Use AI for parsing
371
+ parsed_data = parse_transcript_with_ai(text, progress)
372
 
373
  # Format output text
374
  output_text = format_transcript_output(parsed_data)
 
1091
  background-color: #fff3e0;
1092
  color: #e65100;
1093
  }
1094
+ .model-selection {
1095
+ margin-bottom: 20px;
1096
+ padding: 15px;
1097
+ background: #f8f9fa;
1098
+ border-radius: 8px;
1099
+ }
1100
  """
1101
 
1102
  gr.Markdown("""
 
1105
  Complete each step to get customized learning recommendations.
1106
  """)
1107
 
1108
+ # Model selection section
1109
+ with gr.Group(elem_classes="model-selection"):
1110
+ model_selector = gr.Dropdown(
1111
+ choices=list(MODEL_CHOICES.keys()),
1112
+ value=DEFAULT_MODEL,
1113
+ label="Select AI Model",
1114
+ interactive=True
1115
+ )
1116
+ load_model_btn = gr.Button("Load Selected Model", variant="secondary")
1117
+ model_status = gr.HTML(
1118
+ value="<div class='model-loading'>Model not loaded yet. Please select and load a model.</div>",
1119
+ visible=True
1120
+ )
1121
+
1122
+ # Progress tracker
1123
  with gr.Row():
1124
  with gr.Column(scale=1):
1125
  step1 = gr.Button("1. Upload Transcript", elem_classes="incomplete-tab")
 
1168
  )
1169
  transcript_data = gr.State()
1170
 
1171
+ def process_transcript_and_update(file_obj, current_tab_status, progress=gr.Progress()):
1172
+ output_text, data = parse_transcript(file_obj, progress)
 
 
 
1173
  if "Error" not in output_text:
1174
  new_status = current_tab_status.copy()
1175
  new_status[0] = True
 
1487
  outputs=[tabs, nav_message, quiz_alert]
1488
  )
1489
 
1490
+ # Model loading functions
1491
+ def load_selected_model(model_name, progress=gr.Progress()):
1492
+ try:
1493
+ model_loader.load_model(model_name, progress)
1494
+ if model_loader.loaded:
1495
+ return gr.update(value=f"<div class='alert-box'>{model_name} loaded successfully!</div>", visible=True)
1496
+ else:
1497
+ return gr.update(value=f"<div class='nav-message'>Failed to load model: {model_loader.error}</div>", visible=True)
1498
+ except Exception as e:
1499
+ return gr.update(value=f"<div class='nav-message'>Error: {str(e)}</div>", visible=True)
1500
 
1501
+ load_model_btn.click(
1502
+ fn=load_selected_model,
1503
+ inputs=model_selector,
1504
  outputs=model_status
1505
  )
1506
 
 
1512
  # For Hugging Face Spaces deployment
1513
  if __name__ == "__main__":
1514
  app.launch()
1515
+