OliverPerrin commited on
Commit
2906d4e
Β·
1 Parent(s): a265cf2

Fix Gradio demo: whole-book summaries, emotion sorting, styling

Browse files
Files changed (1) hide show
  1. scripts/demo_gradio.py +86 -32
scripts/demo_gradio.py CHANGED
@@ -76,7 +76,7 @@ TOPIC_EMOJI = {
76
 
77
 
78
  def load_books_data() -> list[dict[str, Any]]:
79
- """Load book paragraphs from JSONL files."""
80
  books = []
81
  library_path = BOOKS_DIR / "library.json"
82
 
@@ -104,6 +104,9 @@ def load_books_data() -> list[dict[str, Any]]:
104
  "title": title,
105
  "paragraphs": paragraphs[:20], # Limit to first 20 substantial paragraphs
106
  "word_count": book_info.get("word_count", 0),
 
 
 
107
  })
108
 
109
  return books
@@ -200,13 +203,18 @@ def analyze_text(text: str) -> tuple[str, str, str]:
200
  emotions = pipe.predict_emotions([text], threshold=0.3)[0]
201
  topic = pipe.predict_topics([text])[0]
202
 
203
- # Format emotions
204
  if emotions.labels:
 
 
 
 
205
  emotion_parts = []
206
- for lbl, score in zip(emotions.labels[:5], emotions.scores[:5], strict=False):
207
  emoji = EMOTION_EMOJI.get(lbl.lower(), "β€’")
208
  emotion_parts.append(f"{emoji} **{lbl.title()}** ({score:.0%})")
209
- emotion_str = "\n".join(emotion_parts)
 
210
  else:
211
  emotion_str = "😐 No strong emotions detected"
212
 
@@ -249,15 +257,47 @@ def get_book_info(title: str) -> str:
249
  if book["title"] == title:
250
  num_paras = len(book["paragraphs"])
251
  word_count = book["word_count"]
252
- return f"**{title}**\n\nπŸ“– {word_count:,} words | {num_paras} excerpts available"
 
253
  return ""
254
 
255
 
256
- def on_book_select(title: str) -> tuple[str, str, int]:
257
- """Handle book selection - return first excerpt and info."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
258
  info = get_book_info(title)
259
  excerpt = get_book_excerpt(title, 0)
260
- return info, excerpt, 0
 
261
 
262
 
263
  def on_paragraph_change(title: str, idx: int) -> str:
@@ -356,7 +396,8 @@ with gr.Blocks(
356
  title="LexiMind - Multi-Task NLP",
357
  theme=gr.themes.Soft(),
358
  css="""
359
- .book-card { padding: 10px; border-radius: 8px; background: #f0f4f8; }
 
360
  .results-panel { min-height: 200px; }
361
  """
362
  ) as demo:
@@ -379,8 +420,8 @@ with gr.Blocks(
379
  gr.Markdown(
380
  """
381
  ### Classic Literature Collection
382
- Browse excerpts from classic novels and see how LexiMind analyzes them.
383
- Select a book, navigate through excerpts, and click **Analyze** to run the model.
384
  """
385
  )
386
 
@@ -393,48 +434,61 @@ with gr.Blocks(
393
  )
394
  book_info = gr.Markdown(elem_classes=["book-card"])
395
 
 
 
396
  para_slider = gr.Slider(
397
  minimum=0,
398
  maximum=19,
399
  step=1,
400
  value=0,
401
- label="πŸ“„ Excerpt Number",
402
  info="Navigate through different parts of the book"
403
  )
404
 
405
- analyze_book_btn = gr.Button("πŸ” Analyze This Excerpt", variant="primary")
406
 
407
  with gr.Column(scale=2):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
408
  book_excerpt = gr.Textbox(
409
- label="πŸ“œ Book Excerpt",
410
- lines=10,
411
- max_lines=15,
412
  interactive=False,
 
413
  )
414
 
415
  with gr.Row():
416
  with gr.Column():
417
- book_summary = gr.Textbox(
418
- label="πŸ“ Generated Summary",
419
- lines=4,
420
  interactive=False,
421
  )
422
  with gr.Column():
423
- with gr.Row():
424
- book_emotions = gr.Markdown(
425
- label="😊 Emotions",
426
- value="*Click Analyze*",
427
- )
428
- book_topic = gr.Markdown(
429
- label="πŸ“‚ Topic",
430
- value="*Click Analyze*",
431
- )
432
 
433
  # Book event handlers
434
  book_dropdown.change(
435
  fn=on_book_select,
436
  inputs=[book_dropdown],
437
- outputs=[book_info, book_excerpt, para_slider],
438
  )
439
 
440
  para_slider.change(
@@ -443,17 +497,17 @@ with gr.Blocks(
443
  outputs=[book_excerpt],
444
  )
445
 
446
- analyze_book_btn.click(
447
  fn=analyze_text,
448
  inputs=[book_excerpt],
449
- outputs=[book_summary, book_emotions, book_topic],
450
  )
451
 
452
  # Initialize with first book
453
  demo.load(
454
  fn=on_book_select,
455
  inputs=[book_dropdown],
456
- outputs=[book_info, book_excerpt, para_slider],
457
  )
458
 
459
  # ===================== TAB 2: EXPLORE NEWS =====================
 
76
 
77
 
78
  def load_books_data() -> list[dict[str, Any]]:
79
+ """Load book data including pre-computed summaries from library.json."""
80
  books = []
81
  library_path = BOOKS_DIR / "library.json"
82
 
 
104
  "title": title,
105
  "paragraphs": paragraphs[:20], # Limit to first 20 substantial paragraphs
106
  "word_count": book_info.get("word_count", 0),
107
+ "summary": book_info.get("summary", ""),
108
+ "topic": book_info.get("topic", ""),
109
+ "emotions": book_info.get("emotions", []),
110
  })
111
 
112
  return books
 
203
  emotions = pipe.predict_emotions([text], threshold=0.3)[0]
204
  topic = pipe.predict_topics([text])[0]
205
 
206
+ # Format emotions - sort by score descending (not alphabetical)
207
  if emotions.labels:
208
+ # Pair labels with scores and sort by score descending
209
+ paired = list(zip(emotions.labels, emotions.scores, strict=False))
210
+ paired_sorted = sorted(paired, key=lambda x: x[1], reverse=True)[:5]
211
+
212
  emotion_parts = []
213
+ for lbl, score in paired_sorted:
214
  emoji = EMOTION_EMOJI.get(lbl.lower(), "β€’")
215
  emotion_parts.append(f"{emoji} **{lbl.title()}** ({score:.0%})")
216
+ # Use double newline for proper Markdown paragraph breaks
217
+ emotion_str = " \n".join(emotion_parts)
218
  else:
219
  emotion_str = "😐 No strong emotions detected"
220
 
 
257
  if book["title"] == title:
258
  num_paras = len(book["paragraphs"])
259
  word_count = book["word_count"]
260
+ topic = book.get("topic", "Unknown")
261
+ return f"**{title}**\n\nπŸ“– {word_count:,} words | {num_paras} excerpts\n\nπŸ“‚ Topic: {topic}"
262
  return ""
263
 
264
 
265
+ def get_book_summary_and_emotions(title: str) -> tuple[str, str, str]:
266
+ """Get pre-computed book summary and emotions from library.json."""
267
+ books = get_books()
268
+ for book in books:
269
+ if book["title"] == title:
270
+ # Get summary
271
+ summary = book.get("summary", "No summary available.")
272
+
273
+ # Get topic
274
+ topic = book.get("topic", "Unknown")
275
+ topic_emoji = TOPIC_EMOJI.get(topic, "πŸ“„")
276
+ topic_str = f"{topic_emoji} **{topic}**"
277
+
278
+ # Get emotions - already sorted by score in library.json
279
+ emotions = book.get("emotions", [])
280
+ if emotions:
281
+ emotion_parts = []
282
+ for emo in emotions[:5]:
283
+ label = emo.get("label", "")
284
+ score = emo.get("score", 0)
285
+ emoji = EMOTION_EMOJI.get(label.lower(), "β€’")
286
+ emotion_parts.append(f"{emoji} **{label.title()}** ({score:.0%})")
287
+ emotion_str = " \n".join(emotion_parts)
288
+ else:
289
+ emotion_str = "😐 No strong emotions detected"
290
+
291
+ return summary, emotion_str, topic_str
292
+ return "No summary available.", "", ""
293
+
294
+
295
+ def on_book_select(title: str) -> tuple[str, str, str, str, str]:
296
+ """Handle book selection - return book info, excerpt, and pre-computed analysis."""
297
  info = get_book_info(title)
298
  excerpt = get_book_excerpt(title, 0)
299
+ summary, emotions, topic = get_book_summary_and_emotions(title)
300
+ return info, excerpt, summary, emotions, topic
301
 
302
 
303
  def on_paragraph_change(title: str, idx: int) -> str:
 
396
  title="LexiMind - Multi-Task NLP",
397
  theme=gr.themes.Soft(),
398
  css="""
399
+ .book-card { padding: 12px; border-radius: 8px; background: #2d3748; color: #f7fafc; }
400
+ .book-card p { color: #f7fafc !important; }
401
  .results-panel { min-height: 200px; }
402
  """
403
  ) as demo:
 
420
  gr.Markdown(
421
  """
422
  ### Classic Literature Collection
423
+ Select a book to see LexiMind's **whole-book analysis**: summary, emotions, and topic.
424
+ You can also browse excerpts and analyze them individually.
425
  """
426
  )
427
 
 
434
  )
435
  book_info = gr.Markdown(elem_classes=["book-card"])
436
 
437
+ gr.Markdown("---")
438
+ gr.Markdown("**πŸ“„ Browse Excerpts:**")
439
  para_slider = gr.Slider(
440
  minimum=0,
441
  maximum=19,
442
  step=1,
443
  value=0,
444
+ label="Excerpt Number",
445
  info="Navigate through different parts of the book"
446
  )
447
 
448
+ analyze_excerpt_btn = gr.Button("πŸ” Analyze This Excerpt", variant="secondary", size="sm")
449
 
450
  with gr.Column(scale=2):
451
+ gr.Markdown("#### πŸ“ Book Summary")
452
+ book_summary = gr.Textbox(
453
+ label="",
454
+ lines=4,
455
+ interactive=False,
456
+ show_label=False,
457
+ )
458
+
459
+ with gr.Row():
460
+ with gr.Column():
461
+ gr.Markdown("#### 😊 Emotions")
462
+ book_emotions = gr.Markdown(value="*Select a book*")
463
+ with gr.Column():
464
+ gr.Markdown("#### πŸ“‚ Topic")
465
+ book_topic = gr.Markdown(value="*Select a book*")
466
+
467
+ gr.Markdown("---")
468
+ gr.Markdown("#### πŸ“œ Book Excerpt")
469
  book_excerpt = gr.Textbox(
470
+ label="",
471
+ lines=6,
472
+ max_lines=10,
473
  interactive=False,
474
+ show_label=False,
475
  )
476
 
477
  with gr.Row():
478
  with gr.Column():
479
+ excerpt_summary = gr.Textbox(
480
+ label="πŸ“ Excerpt Summary",
481
+ lines=3,
482
  interactive=False,
483
  )
484
  with gr.Column():
485
+ excerpt_emotions = gr.Markdown(value="*Click Analyze Excerpt*")
 
 
 
 
 
 
 
 
486
 
487
  # Book event handlers
488
  book_dropdown.change(
489
  fn=on_book_select,
490
  inputs=[book_dropdown],
491
+ outputs=[book_info, book_excerpt, book_summary, book_emotions, book_topic],
492
  )
493
 
494
  para_slider.change(
 
497
  outputs=[book_excerpt],
498
  )
499
 
500
+ analyze_excerpt_btn.click(
501
  fn=analyze_text,
502
  inputs=[book_excerpt],
503
+ outputs=[excerpt_summary, excerpt_emotions, book_topic],
504
  )
505
 
506
  # Initialize with first book
507
  demo.load(
508
  fn=on_book_select,
509
  inputs=[book_dropdown],
510
+ outputs=[book_info, book_excerpt, book_summary, book_emotions, book_topic],
511
  )
512
 
513
  # ===================== TAB 2: EXPLORE NEWS =====================