shayekh commited on
Commit
2f803b9
Β·
verified Β·
1 Parent(s): 63f07fd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +138 -12
app.py CHANGED
@@ -29,14 +29,13 @@ else:
29
 
30
  os.environ['PLAYWRIGHT_BROWSERS_PATH'] = "/home/user/huggingface/ms-playwright"
31
  # os.system("playwright install chromium")
32
- # result = subprocess.run(
33
- # [sys.executable, "-m", "playwright", "install", "chromium"],
34
- # env={**os.environ},
35
- # check=True,
36
- # stdout=subprocess.PIPE,
37
- # stderr=subprocess.PIPE
38
- # )
39
- subprocess.run(["playwright", "install"])
40
 
41
  import gradio as gr
42
  import fitz # PyMuPDF
@@ -56,6 +55,20 @@ from transformers import AutoProcessor, AutoModelForImageTextToText
56
  # tts = None
57
  # voice_style = None
58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  def extract_pdf_content(pdf_path, max_pages=2):
60
  """Extract text and images from up to max_pages of a PDF."""
61
  doc = fitz.open(pdf_path)
@@ -203,9 +216,20 @@ Text:
203
  padding=True
204
  ).to("cuda")
205
 
206
- from transformers import TextIteratorStreamer
 
 
 
 
207
  from threading import Thread
208
 
 
 
 
 
 
 
 
209
  streamer = TextIteratorStreamer(processor.tokenizer, skip_prompt=True, skip_special_tokens=True)
210
  generation_kwargs = dict(
211
  **inputs,
@@ -213,6 +237,7 @@ Text:
213
  max_new_tokens=2048*16,
214
  do_sample=True,
215
  repetition_penalty=repetition_penalty_val,
 
216
  )
217
 
218
  if len(images) > 0:
@@ -220,7 +245,22 @@ Text:
220
  else:
221
  generation_kwargs.update(dict(temperature=1.0, top_p=0.95, top_k=20, min_p=0.0))
222
 
223
- thread = Thread(target=model.generate, kwargs=generation_kwargs)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
  thread.start()
225
 
226
  output_text = ""
@@ -228,6 +268,85 @@ Text:
228
  output_text += new_text
229
  yield output_text, None
230
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231
  # DEBUG: Log raw output text
232
  with open("log/debug_vlm_output.txt", "w", encoding="utf-8") as f:
233
  f.write(output_text)
@@ -890,7 +1009,7 @@ def create_demo():
890
  with gr.Column(scale=1):
891
  # url_input = gr.Textbox(label="Enter a Website URL 🌐", placeholder=r"e.g. https://storykorean.com/stories?level=beginner&story=tiger", value=r"https://storykorean.com/stories?level=beginner&story=tiger")
892
  # https://www.bbc.com/korean/articles/c5yz89k5dw0o
893
- url_input = gr.Textbox(label="Enter a Website URL 🌐", placeholder=r"e.g. https://www.bbc.com/korean/articles/c5yz89k5dw0o", value=r"https://www.bbc.com/korean/articles/c5yz89k5dw0o")
894
 
895
  pdf_input = gr.File(label="Or Upload Book PDF πŸ“š", file_types=[".pdf"], value=example_pdf)
896
 
@@ -911,6 +1030,7 @@ def create_demo():
911
 
912
  with gr.Row():
913
  submit_btn = gr.Button("✨ Generate Flashcards ✨", variant="primary")
 
914
  stop_btn = gr.Button("πŸ›‘ Stop Generation", variant="stop")
915
 
916
  with gr.Column(scale=2):
@@ -924,13 +1044,19 @@ def create_demo():
924
  last_source_state = gr.State(None)
925
  last_korean_words_state = gr.State(None)
926
 
 
 
 
 
 
927
  generate_event = submit_btn.click(
928
  fn=process_pdf,
929
  inputs=[pdf_input, url_input, translit_lang, translit_format, target_lang, max_text_char_input, repetition_penalty_input, last_source_state, last_korean_words_state],
930
  outputs=[output_html, last_source_state, last_korean_words_state, stream_box, extracted_text_box, extracted_images_gallery]
931
  )
932
 
933
- stop_btn.click(fn=None, inputs=None, outputs=None, cancels=[generate_event])
 
934
 
935
  # Force autoscroll using Custom JS
936
  stream_box.change(
 
29
 
30
  os.environ['PLAYWRIGHT_BROWSERS_PATH'] = "/home/user/huggingface/ms-playwright"
31
  # os.system("playwright install chromium")
32
+ result = subprocess.run(
33
+ [sys.executable, "-m", "playwright", "install", "chromium"],
34
+ env={**os.environ},
35
+ check=True,
36
+ stdout=subprocess.PIPE,
37
+ stderr=subprocess.PIPE
38
+ )
 
39
 
40
  import gradio as gr
41
  import fitz # PyMuPDF
 
55
  # tts = None
56
  # voice_style = None
57
 
58
+ global_stop_thinking = [False]
59
+ global_kill_threads = [False]
60
+
61
+ def set_stop_thinking():
62
+ global_stop_thinking[0] = True
63
+ print(f"[STOP-THINK] set_stop_thinking CALLED! Flag is now: {global_stop_thinking[0]}")
64
+ return gr.update(value="⚑ Forcing generation...")
65
+
66
+ def set_kill_threads():
67
+ global_kill_threads[0] = True
68
+ print(f"[STOP-THINK] set_kill_threads CALLED! Flag is now: {global_kill_threads[0]}")
69
+ return gr.update(value="πŸ›‘ Stopping...")
70
+
71
+
72
  def extract_pdf_content(pdf_path, max_pages=2):
73
  """Extract text and images from up to max_pages of a PDF."""
74
  doc = fitz.open(pdf_path)
 
216
  padding=True
217
  ).to("cuda")
218
 
219
+ global_stop_thinking[0] = False
220
+ global_kill_threads[0] = False
221
+ print(f"[STOP-THINK] Flags RESET. stop_thinking={global_stop_thinking[0]}, kill={global_kill_threads[0]}")
222
+
223
+ from transformers import TextIteratorStreamer, StoppingCriteria, StoppingCriteriaList
224
  from threading import Thread
225
 
226
+ class StopThinkingCriteria(StoppingCriteria):
227
+ def __call__(self, input_ids, scores, **kwargs):
228
+ val = global_stop_thinking[0] or global_kill_threads[0]
229
+ if val:
230
+ print(f"[STOP-THINK] Criteria returning True! stop={global_stop_thinking[0]} kill={global_kill_threads[0]}")
231
+ return val
232
+
233
  streamer = TextIteratorStreamer(processor.tokenizer, skip_prompt=True, skip_special_tokens=True)
234
  generation_kwargs = dict(
235
  **inputs,
 
237
  max_new_tokens=2048*16,
238
  do_sample=True,
239
  repetition_penalty=repetition_penalty_val,
240
+ stopping_criteria=StoppingCriteriaList([StopThinkingCriteria()])
241
  )
242
 
243
  if len(images) > 0:
 
245
  else:
246
  generation_kwargs.update(dict(temperature=1.0, top_p=0.95, top_k=20, min_p=0.0))
247
 
248
+ generation_result = []
249
+ def generate_and_capture(**kwargs):
250
+ try:
251
+ out = model.generate(**kwargs)
252
+ generation_result.append(out)
253
+ except Exception as e:
254
+ import traceback
255
+ print(f"\n[THREAD1 ERROR] model.generate crashed: {e}")
256
+ traceback.print_exc()
257
+ finally:
258
+ try:
259
+ streamer.end()
260
+ except Exception:
261
+ pass
262
+
263
+ thread = Thread(target=generate_and_capture, kwargs=generation_kwargs)
264
  thread.start()
265
 
266
  output_text = ""
 
268
  output_text += new_text
269
  yield output_text, None
270
 
271
+ thread.join()
272
+
273
+ if global_kill_threads[0]:
274
+ yield output_text + "\n\n[Generation completely stopped by user.]", None
275
+ return
276
+
277
+ if global_stop_thinking[0]:
278
+ global_stop_thinking[0] = False
279
+ print(f"[STOP-THINK] INJECTION PATH entered. Reset flag to: {global_stop_thinking[0]}")
280
+
281
+ # Inject the closure of thinking and start of JSON
282
+ injection_text = "\n</think>\n\n```json\n[\n"
283
+ output_text += injection_text
284
+ yield output_text, None
285
+
286
+ # Restart generation with updated context
287
+ generated_ids = generation_result[0]
288
+ injection_ids = processor.tokenizer(injection_text, return_tensors="pt", add_special_tokens=False).input_ids.to("cuda")
289
+ new_input_ids = torch.cat([generated_ids, injection_ids], dim=-1)
290
+
291
+ # Update attention mask
292
+ new_mask = torch.cat([
293
+ inputs["attention_mask"],
294
+ torch.ones((1, new_input_ids.shape[1] - inputs["attention_mask"].shape[1]), dtype=inputs["attention_mask"].dtype, device="cuda")
295
+ ], dim=-1)
296
+
297
+ new_inputs = {
298
+ "input_ids": new_input_ids,
299
+ "attention_mask": new_mask
300
+ }
301
+
302
+ # Carry over only the visual features; discard stale keys like input_token_type or rope_deltas
303
+ keys_to_keep = ["pixel_values", "image_grid_thw", "pixel_values_videos", "video_grid_thw"]
304
+ for k in keys_to_keep:
305
+ if k in inputs:
306
+ new_inputs[k] = inputs[k]
307
+
308
+ class KillCriteria(StoppingCriteria):
309
+ def __call__(self, input_ids, scores, **kwargs):
310
+ return global_kill_threads[0]
311
+
312
+ new_streamer = TextIteratorStreamer(processor.tokenizer, skip_prompt=True, skip_special_tokens=True)
313
+ new_generation_kwargs = dict(
314
+ **new_inputs,
315
+ streamer=new_streamer,
316
+ max_new_tokens=2048*16,
317
+ do_sample=True,
318
+ repetition_penalty=repetition_penalty_val,
319
+ stopping_criteria=StoppingCriteriaList([KillCriteria()])
320
+ )
321
+
322
+ if len(images) > 0:
323
+ new_generation_kwargs.update(dict(temperature=0.6, top_p=0.95, top_k=20, min_p=0.0))
324
+ else:
325
+ new_generation_kwargs.update(dict(temperature=1.0, top_p=0.95, top_k=20, min_p=0.0))
326
+
327
+ def thread2_target(**kwargs):
328
+ try:
329
+ model.generate(**kwargs)
330
+ except Exception as e:
331
+ import traceback
332
+ print(f"\n[THREAD2 ERROR] model.generate crashed: {e}")
333
+ traceback.print_exc()
334
+ finally:
335
+ # Always unblock the streamer to prevent Gradio UI from hanging permanently
336
+ try:
337
+ new_streamer.end()
338
+ except Exception:
339
+ pass
340
+
341
+ thread2 = Thread(target=thread2_target, kwargs=new_generation_kwargs)
342
+ thread2.start()
343
+
344
+ for new_text in new_streamer:
345
+ output_text += new_text
346
+ yield output_text, None
347
+
348
+ thread2.join()
349
+
350
  # DEBUG: Log raw output text
351
  with open("log/debug_vlm_output.txt", "w", encoding="utf-8") as f:
352
  f.write(output_text)
 
1009
  with gr.Column(scale=1):
1010
  # url_input = gr.Textbox(label="Enter a Website URL 🌐", placeholder=r"e.g. https://storykorean.com/stories?level=beginner&story=tiger", value=r"https://storykorean.com/stories?level=beginner&story=tiger")
1011
  # https://www.bbc.com/korean/articles/c5yz89k5dw0o
1012
+ url_input = gr.Textbox(label="Enter a Website URL 🌐", placeholder=r"e.g. https://www.koreanstudyjunkie.com/post/korean-reading-exercise-for-all-levels-beginner-intermediate-advanced", value=r"https://www.koreanstudyjunkie.com/post/korean-reading-exercise-for-all-levels-beginner-intermediate-advanced")
1013
 
1014
  pdf_input = gr.File(label="Or Upload Book PDF πŸ“š", file_types=[".pdf"], value=example_pdf)
1015
 
 
1030
 
1031
  with gr.Row():
1032
  submit_btn = gr.Button("✨ Generate Flashcards ✨", variant="primary")
1033
+ stop_thinking_btn = gr.Button("⚑ Stop thinking, Generate now", variant="secondary")
1034
  stop_btn = gr.Button("πŸ›‘ Stop Generation", variant="stop")
1035
 
1036
  with gr.Column(scale=2):
 
1044
  last_source_state = gr.State(None)
1045
  last_korean_words_state = gr.State(None)
1046
 
1047
+ def reset_btn_text():
1048
+ return gr.update(value="⚑ Stop thinking, Generate now"), gr.update(value="πŸ›‘ Stop Generation")
1049
+
1050
+ submit_btn.click(fn=reset_btn_text, inputs=None, outputs=[stop_thinking_btn, stop_btn], queue=False)
1051
+
1052
  generate_event = submit_btn.click(
1053
  fn=process_pdf,
1054
  inputs=[pdf_input, url_input, translit_lang, translit_format, target_lang, max_text_char_input, repetition_penalty_input, last_source_state, last_korean_words_state],
1055
  outputs=[output_html, last_source_state, last_korean_words_state, stream_box, extracted_text_box, extracted_images_gallery]
1056
  )
1057
 
1058
+ stop_thinking_btn.click(fn=set_stop_thinking, inputs=None, outputs=stop_thinking_btn, queue=False)
1059
+ stop_btn.click(fn=set_kill_threads, inputs=None, outputs=stop_btn, queue=False).then(fn=None, inputs=None, outputs=None, cancels=[generate_event])
1060
 
1061
  # Force autoscroll using Custom JS
1062
  stream_box.change(