Nischal Subedi commited on
Commit
b29695d
·
1 Parent(s): a07f515
Files changed (1) hide show
  1. app.py +100 -39
app.py CHANGED
@@ -5,7 +5,6 @@ from functools import lru_cache
5
  import re
6
 
7
  import gradio as gr
8
- # import gradio.themes as themes # Not directly used for theme dropdown, but kept if you had other theme-related utilities.
9
 
10
  try:
11
  # Assuming vector_db.py exists in the same directory or is installed
@@ -260,11 +259,12 @@ Answer:"""
260
 
261
  # Check if the answer already contains an error message (from deeper within process_query)
262
  if "<div class='error-message'>" in answer:
263
- return answer # Return the pre-formatted error message directly
 
264
  else:
265
- # Format the successful response with the new UI structure
266
- formatted_response = f"<div class='response-header'><span class='response-icon'>📜</span>Response for {state}</div><hr class='divider'>{answer}"
267
- return formatted_response
268
 
269
  try:
270
  available_states_list = self.get_states()
@@ -297,21 +297,20 @@ Answer:"""
297
 
298
 
299
  # Custom CSS for better UI design, clear boundaries, and text alignment for HuggingFace
300
- # This CSS overrides Gradio defaults to create the desired look and feel.
301
  custom_css = """
302
  /* Import legible fonts from Google Fonts */
303
  @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Poppins:wght@600;700;800&display=swap');
304
 
305
- /* Root variables for consistent theming - adjusted for calm_seafoam feel */
306
  :root {
307
- --primary-color: #4CAF50; /* A pleasant green */
308
- --primary-hover: #45a049;
309
- --background-primary: #F0F8F8; /* Light seafoam background */
310
- --background-secondary: #E8F0F0; /* Slightly darker for contrast */
311
- --text-primary: #2C3E50; /* Darker text for readability */
312
- --text-secondary: #5F7C8A; /* Muted text */
313
- --border-color: #B2D8D8; /* Seafoam border */
314
- --border-focus: #4CAF50; /* Focus color matches primary */
315
  --shadow-sm: 0 1px 3px rgba(0,0,0,0.08);
316
  --shadow-md: 0 4px 10px rgba(0,0,0,0.1);
317
  --shadow-lg: 0 10px 20px rgba(0,0,0,0.15);
@@ -321,7 +320,6 @@ Answer:"""
321
  }
322
 
323
  /* Dark mode variables - for consistency if a dark mode toggle were present */
324
- /* calm_seafoam theme itself is light, but if a `dark` class is applied to body: */
325
  body.dark {
326
  --background-primary: #1F303A; /* Dark blue-green */
327
  --background-secondary: #2C404B;
@@ -358,30 +356,61 @@ Answer:"""
358
  margin-bottom: 1.5rem !important;
359
  text-align: center !important; /* Center text within header */
360
  box-shadow: var(--shadow-md) !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
361
  }
 
362
  .app-header-logo {
363
- font-size: 3.5rem !important; /* Larger icon */
364
  margin-bottom: 0.75rem !important;
365
  display: block !important;
366
  color: var(--primary-color) !important; /* Theme color */
 
 
 
 
 
 
 
 
 
 
367
  }
 
368
  .app-header-title {
369
  font-family: 'Poppins', sans-serif !important;
370
- font-size: 2.8rem !important; /* Larger title */
371
  font-weight: 800 !important; /* Bolder */
372
  color: var(--text-primary) !important;
373
  margin: 0 0 0.75rem 0 !important;
374
  line-height: 1.1 !important;
375
- letter-spacing: -0.02em !important; /* Slightly tighter spacing */
 
 
376
  }
377
  .app-header-tagline {
378
- font-size: 1.2rem !important;
379
  color: var(--text-secondary) !important;
380
  font-weight: 400 !important;
381
  margin: 0 !important;
382
  max-width: 700px; /* Constrain tagline width */
383
  margin-left: auto;
384
  margin-right: auto;
 
 
385
  }
386
 
387
  /* Main container with consistent spacing */
@@ -390,24 +419,26 @@ Answer:"""
390
  flex-direction: column !important;
391
  gap: 1.25rem !important; /* Consistent spacing between cards */
392
  }
393
- /* Card sections with clear boundaries (boundeyes) */
394
  .dashboard-card-section {
395
  background: var(--background-primary) !important;
396
  border: 2px solid var(--border-color) !important; /* Distinct border */
397
  border-radius: 12px !important;
398
  padding: 1.75rem !important; /* Consistent padding */
399
  box-shadow: var(--shadow-sm) !important; /* Subtle shadow */
400
- transition: all 0.2s ease !important;
 
401
  }
402
  .dashboard-card-section:hover {
403
- box-shadow: var(--shadow-md) !important; /* Enhanced shadow on hover */
 
404
  }
405
 
406
  /* Centered section titles with improved typography */
407
  .sub-section-title {
408
  font-family: 'Poppins', sans-serif !important;
409
- font-size: 1.6rem !important;
410
- font-weight: 700 !important;
411
  color: var(--text-primary) !important;
412
  text-align: center !important; /* Centered text */
413
  margin: 0 0 1.25rem 0 !important; /* More space below title */
@@ -444,7 +475,7 @@ Answer:"""
444
  font-size: 0.98rem !important;
445
  font-family: 'Inter', sans-serif !important;
446
  color: var(--text-primary) !important;
447
- transition: all 0.2s ease !important;
448
  box-shadow: var(--shadow-sm) !important;
449
  }
450
  .gradio-textbox textarea:focus,
@@ -453,7 +484,7 @@ Answer:"""
453
  .gradio-dropdown .primary-wrap.focused { /* Apply focus style to dropdown wrap */
454
  outline: none !important;
455
  border-color: var(--border-focus) !important; /* Distinct border on focus */
456
- box-shadow: 0 0 0 3px rgba(76, 175, 80, 0.15) !important; /* Soft glow on focus */
457
  }
458
 
459
  /* Label styling for better readability */
@@ -482,7 +513,7 @@ Answer:"""
482
  flex: 1 !important;
483
  }
484
 
485
- /* Button styling improvements */
486
  .button-row {
487
  display: flex !important;
488
  gap: 1rem !important;
@@ -494,7 +525,7 @@ Answer:"""
494
  border-radius: 9px !important; /* Slightly more rounded */
495
  font-weight: 600 !important; /* Bolder text */
496
  font-size: 1rem !important;
497
- transition: all 0.25s ease !important;
498
  cursor: pointer !important;
499
  border: 2px solid transparent !important;
500
  text-align: center !important; /* Ensure button text is centered */
@@ -509,6 +540,10 @@ Answer:"""
509
  box-shadow: var(--shadow-md) !important;
510
  transform: translateY(-2px) !important; /* Subtle lift effect on hover */
511
  }
 
 
 
 
512
  .gr-button-secondary {
513
  background: transparent !important;
514
  color: var(--text-primary) !important;
@@ -519,21 +554,41 @@ Answer:"""
519
  border-color: var(--primary-color) !important;
520
  transform: translateY(-2px) !important;
521
  }
 
 
 
 
522
 
523
- /* Output styling with clear boundaries (boundeyes are clear) */
524
  .output-content-wrapper {
525
  background: var(--background-primary) !important;
526
  border: 2px solid var(--border-color) !important; /* Clear border */
527
  border-radius: 8px !important;
528
  padding: 1.5rem !important;
529
  min-height: 150px !important; /* More space for output */
530
- font-size: 1rem !important;
531
- line-height: 1.7 !important;
532
  color: var(--text-primary) !important;
533
- overflow-wrap: break-word; /* Ensure long words wrap */
534
- word-break: break-word; /* Ensure long words wrap */
535
- white-space: pre-wrap; /* Preserve formatting for newlines in markdown */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
536
  }
 
537
  .response-header {
538
  font-size: 1.3rem !important;
539
  font-weight: 700 !important;
@@ -552,7 +607,6 @@ Answer:"""
552
  border-top: 1px dashed var(--border-color) !important; /* Dashed divider for visual separation */
553
  margin: 1rem 0 !important;
554
  }
555
-
556
  /* Error message styling */
557
  .error-message {
558
  background: var(--error-bg) !important;
@@ -566,6 +620,9 @@ Answer:"""
566
  font-size: 0.95rem !important;
567
  font-weight: 500 !important;
568
  line-height: 1.6 !important;
 
 
 
569
  }
570
  .error-message a {
571
  color: var(--error-text) !important;
@@ -592,9 +649,11 @@ Answer:"""
592
  color: var(--text-secondary) !important;
593
  font-style: italic !important;
594
  font-size: 1.1rem !important;
 
 
595
  }
596
 
597
- /* Examples table styling */
598
  .examples-section .gr-samples-table {
599
  border: 2px solid var(--border-color) !important;
600
  border-radius: 8px !important;
@@ -618,9 +677,11 @@ Answer:"""
618
  color: var(--text-primary) !important;
619
  border-top: 1px solid var(--border-color) !important;
620
  cursor: pointer !important;
 
621
  }
622
  .examples-section .gr-samples-table tr:hover td {
623
  background: var(--background-secondary) !important;
 
624
  }
625
  /* Hide Gradio default elements for examples for cleaner look */
626
  .gr-examples .gr-label,
@@ -754,10 +815,10 @@ Answer:"""
754
  clear_button = gr.Button("Clear", variant="secondary", elem_classes=["gr-button-secondary"])
755
  submit_button = gr.Button("Submit Query", variant="primary", elem_classes=["gr-button-primary"])
756
 
757
- # Output Display Card
758
  with gr.Group(elem_classes="dashboard-card-section"):
759
  gr.Markdown("<h3 class='sub-section-title'>Legal Assistant's Response</h3>") # Centered by CSS
760
- output = gr.Markdown(
761
  value="<div class='placeholder'>The answer will appear here after submitting your query.</div>",
762
  elem_classes="output-content-wrapper" # Custom class for output styling
763
  )
 
5
  import re
6
 
7
  import gradio as gr
 
8
 
9
  try:
10
  # Assuming vector_db.py exists in the same directory or is installed
 
259
 
260
  # Check if the answer already contains an error message (from deeper within process_query)
261
  if "<div class='error-message'>" in answer:
262
+ # Error messages are returned directly as they contain their own styling
263
+ return answer
264
  else:
265
+ # Wrap successful response in a div with an animation class
266
+ formatted_response_content = f"<div class='response-header'><span class='response-icon'>📜</span>Response for {state}</div><hr class='divider'>{answer}"
267
+ return f"<div class='animated-output-content'>{formatted_response_content}</div>"
268
 
269
  try:
270
  available_states_list = self.get_states()
 
297
 
298
 
299
  # Custom CSS for better UI design, clear boundaries, and text alignment for HuggingFace
 
300
  custom_css = """
301
  /* Import legible fonts from Google Fonts */
302
  @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Poppins:wght@600;700;800&display=swap');
303
 
304
+ /* Root variables for consistent theming - adjusted for very light calm_seafoam feel */
305
  :root {
306
+ --primary-color: #3cb371; /* Medium Sea Green (vibrant seafoam) */
307
+ --primary-hover: #339966;
308
+ --background-primary: hsl(180, 100%, 98%); /* Very light seafoam for main cards */
309
+ --background-secondary: hsl(180, 100%, 96%); /* Slightly darker for overall app background */
310
+ --text-primary: hsl(210, 20%, 20%); /* Dark blue-gray for main text */
311
+ --text-secondary: hsl(210, 10%, 45%); /* Muted blue-gray for secondary text */
312
+ --border-color: hsl(180, 30%, 85%); /* Subtle seafoam gray for borders */
313
+ --border-focus: #3cb371; /* Focus color matches primary */
314
  --shadow-sm: 0 1px 3px rgba(0,0,0,0.08);
315
  --shadow-md: 0 4px 10px rgba(0,0,0,0.1);
316
  --shadow-lg: 0 10px 20px rgba(0,0,0,0.15);
 
320
  }
321
 
322
  /* Dark mode variables - for consistency if a dark mode toggle were present */
 
323
  body.dark {
324
  --background-primary: #1F303A; /* Dark blue-green */
325
  --background-secondary: #2C404B;
 
356
  margin-bottom: 1.5rem !important;
357
  text-align: center !important; /* Center text within header */
358
  box-shadow: var(--shadow-md) !important;
359
+ position: relative; /* For potential pseudo-element effects */
360
+ overflow: hidden; /* For any overflow animations */
361
+ }
362
+ .app-header-wrapper::before { /* Subtle background pattern for dynamism */
363
+ content: '';
364
+ position: absolute;
365
+ top: 0;
366
+ left: 0;
367
+ width: 100%;
368
+ height: 100%;
369
+ background: radial-gradient(circle at top left, rgba(60,179,113,0.05) 0%, transparent 40%),
370
+ radial-gradient(circle at bottom right, rgba(60,179,113,0.05) 0%, transparent 40%);
371
+ z-index: 0;
372
+ opacity: 0.8;
373
+ pointer-events: none;
374
  }
375
+
376
  .app-header-logo {
377
+ font-size: 4.5rem !important; /* Larger icon */
378
  margin-bottom: 0.75rem !important;
379
  display: block !important;
380
  color: var(--primary-color) !important; /* Theme color */
381
+ position: relative;
382
+ z-index: 1; /* Bring icon to front of pseudo-element */
383
+ /* Animation for dynamism */
384
+ animation: float-icon 3s ease-in-out infinite alternate;
385
+ }
386
+ /* Keyframes for floating icon */
387
+ @keyframes float-icon {
388
+ 0% { transform: translateY(0px); }
389
+ 50% { transform: translateY(-5px); }
390
+ 100% { transform: translateY(0px); }
391
  }
392
+
393
  .app-header-title {
394
  font-family: 'Poppins', sans-serif !important;
395
+ font-size: 3rem !important; /* Even larger title */
396
  font-weight: 800 !important; /* Bolder */
397
  color: var(--text-primary) !important;
398
  margin: 0 0 0.75rem 0 !important;
399
  line-height: 1.1 !important;
400
+ letter-spacing: -0.03em !important; /* Tighter spacing */
401
+ position: relative;
402
+ z-index: 1;
403
  }
404
  .app-header-tagline {
405
+ font-size: 1.25rem !important; /* Slightly larger tagline */
406
  color: var(--text-secondary) !important;
407
  font-weight: 400 !important;
408
  margin: 0 !important;
409
  max-width: 700px; /* Constrain tagline width */
410
  margin-left: auto;
411
  margin-right: auto;
412
+ position: relative;
413
+ z-index: 1;
414
  }
415
 
416
  /* Main container with consistent spacing */
 
419
  flex-direction: column !important;
420
  gap: 1.25rem !important; /* Consistent spacing between cards */
421
  }
422
+ /* Card sections with clear boundaries (boundeyes) and subtle dynamic effects */
423
  .dashboard-card-section {
424
  background: var(--background-primary) !important;
425
  border: 2px solid var(--border-color) !important; /* Distinct border */
426
  border-radius: 12px !important;
427
  padding: 1.75rem !important; /* Consistent padding */
428
  box-shadow: var(--shadow-sm) !important; /* Subtle shadow */
429
+ transition: all 0.3s ease-out !important; /* Smoother transition */
430
+ cursor: default; /* Indicate not directly clickable (unless examples) */
431
  }
432
  .dashboard-card-section:hover {
433
+ box-shadow: var(--shadow-md) !important;
434
+ transform: translateY(-3px) !important; /* More pronounced lift */
435
  }
436
 
437
  /* Centered section titles with improved typography */
438
  .sub-section-title {
439
  font-family: 'Poppins', sans-serif !important;
440
+ font-size: 1.7rem !important; /* Slightly larger */
441
+ font-weight: 700 !important; /* Bolder */
442
  color: var(--text-primary) !important;
443
  text-align: center !important; /* Centered text */
444
  margin: 0 0 1.25rem 0 !important; /* More space below title */
 
475
  font-size: 0.98rem !important;
476
  font-family: 'Inter', sans-serif !important;
477
  color: var(--text-primary) !important;
478
+ transition: border-color 0.2s ease, box-shadow 0.2s ease !important; /* Smooth transitions */
479
  box-shadow: var(--shadow-sm) !important;
480
  }
481
  .gradio-textbox textarea:focus,
 
484
  .gradio-dropdown .primary-wrap.focused { /* Apply focus style to dropdown wrap */
485
  outline: none !important;
486
  border-color: var(--border-focus) !important; /* Distinct border on focus */
487
+ box-shadow: 0 0 0 4px rgba(60, 179, 113, 0.2) !important; /* Broader, softer glow on focus */
488
  }
489
 
490
  /* Label styling for better readability */
 
513
  flex: 1 !important;
514
  }
515
 
516
+ /* Button styling improvements with active state for dynamism */
517
  .button-row {
518
  display: flex !important;
519
  gap: 1rem !important;
 
525
  border-radius: 9px !important; /* Slightly more rounded */
526
  font-weight: 600 !important; /* Bolder text */
527
  font-size: 1rem !important;
528
+ transition: all 0.2s ease-out !important; /* Smooth transition for hover/active */
529
  cursor: pointer !important;
530
  border: 2px solid transparent !important;
531
  text-align: center !important; /* Ensure button text is centered */
 
540
  box-shadow: var(--shadow-md) !important;
541
  transform: translateY(-2px) !important; /* Subtle lift effect on hover */
542
  }
543
+ .gr-button-primary:active { /* Press down effect on click */
544
+ transform: translateY(1px) !important;
545
+ box-shadow: none !important;
546
+ }
547
  .gr-button-secondary {
548
  background: transparent !important;
549
  color: var(--text-primary) !important;
 
554
  border-color: var(--primary-color) !important;
555
  transform: translateY(-2px) !important;
556
  }
557
+ .gr-button-secondary:active { /* Press down effect on click */
558
+ transform: translateY(1px) !important;
559
+ box-shadow: none !important;
560
+ }
561
 
562
+ /* Output styling with clear boundaries (boundeyes are clear) and dynamic fade-in */
563
  .output-content-wrapper {
564
  background: var(--background-primary) !important;
565
  border: 2px solid var(--border-color) !important; /* Clear border */
566
  border-radius: 8px !important;
567
  padding: 1.5rem !important;
568
  min-height: 150px !important; /* More space for output */
 
 
569
  color: var(--text-primary) !important;
570
+ /* Ensure the inner animated content fits well */
571
+ display: flex;
572
+ flex-direction: column;
573
+ justify-content: center; /* Center content vertically if small */
574
+ align-items: center; /* Center content horizontally if small */
575
+ }
576
+ /* The div holding the actual response content, enabling fade-in animation */
577
+ .animated-output-content {
578
+ opacity: 0;
579
+ animation: fadeInAndSlideUp 0.7s ease-out forwards; /* More pronounced animation */
580
+ width: 100%; /* Take full width of parent */
581
+ /* Preserve formatting within the animated content */
582
+ white-space: pre-wrap;
583
+ overflow-wrap: break-word;
584
+ word-break: break-word;
585
+ text-align: left !important; /* Ensure text is left-aligned within this div */
586
+ }
587
+ @keyframes fadeInAndSlideUp {
588
+ from { opacity: 0; transform: translateY(15px); }
589
+ to { opacity: 1; transform: translateY(0); }
590
  }
591
+
592
  .response-header {
593
  font-size: 1.3rem !important;
594
  font-weight: 700 !important;
 
607
  border-top: 1px dashed var(--border-color) !important; /* Dashed divider for visual separation */
608
  margin: 1rem 0 !important;
609
  }
 
610
  /* Error message styling */
611
  .error-message {
612
  background: var(--error-bg) !important;
 
620
  font-size: 0.95rem !important;
621
  font-weight: 500 !important;
622
  line-height: 1.6 !important;
623
+ text-align: left !important; /* Ensure error message text is left aligned */
624
+ width: 100%; /* Take full width of parent */
625
+ box-sizing: border-box; /* Include padding/border in width */
626
  }
627
  .error-message a {
628
  color: var(--error-text) !important;
 
649
  color: var(--text-secondary) !important;
650
  font-style: italic !important;
651
  font-size: 1.1rem !important;
652
+ width: 100%; /* Ensure it takes full width of parent */
653
+ box-sizing: border-box; /* Include padding/border in width */
654
  }
655
 
656
+ /* Examples table styling with dynamic hover */
657
  .examples-section .gr-samples-table {
658
  border: 2px solid var(--border-color) !important;
659
  border-radius: 8px !important;
 
677
  color: var(--text-primary) !important;
678
  border-top: 1px solid var(--border-color) !important;
679
  cursor: pointer !important;
680
+ transition: background 0.2s ease, transform 0.1s ease !important; /* Smooth transitions */
681
  }
682
  .examples-section .gr-samples-table tr:hover td {
683
  background: var(--background-secondary) !important;
684
+ transform: translateX(5px); /* Subtle slide on hover */
685
  }
686
  /* Hide Gradio default elements for examples for cleaner look */
687
  .gr-examples .gr-label,
 
815
  clear_button = gr.Button("Clear", variant="secondary", elem_classes=["gr-button-secondary"])
816
  submit_button = gr.Button("Submit Query", variant="primary", elem_classes=["gr-button-primary"])
817
 
818
+ # Output Display Card - Using gr.HTML for better animation control
819
  with gr.Group(elem_classes="dashboard-card-section"):
820
  gr.Markdown("<h3 class='sub-section-title'>Legal Assistant's Response</h3>") # Centered by CSS
821
+ output = gr.HTML( # Changed to gr.HTML to wrap content with animation class
822
  value="<div class='placeholder'>The answer will appear here after submitting your query.</div>",
823
  elem_classes="output-content-wrapper" # Custom class for output styling
824
  )