EngrMuhammadBilal commited on
Commit
be4e843
·
verified ·
1 Parent(s): ad26c8e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +136 -69
app.py CHANGED
@@ -11,119 +11,186 @@ from docx.shared import Pt
11
  from string import Template
12
 
13
  # =========================
14
- # Branding & Palette
15
  # =========================
16
  APP_NAME = "ScholarLens"
17
  TAGLINE = "Query your literature, get page-level proof"
18
 
 
 
 
 
19
  PALETTE = {
20
- "navy": "#083D77", # dark background
21
- "gold": "#F2B400", # primary buttons / accents
22
- "ice": "#FBF8F9", # off-white
23
- "maroon": "#8B1E1E", # emphasis chips / separators
24
- "amber": "#F5C26B", # secondary accent
25
- "text_on_dark": "#EAF2FF", # light text on dark
26
- "text_on_light": "#0B1220" # dark text on light (gold/amber)
 
 
 
 
 
 
 
 
 
27
  }
28
 
29
  def build_custom_css():
30
- """Dark UI with light text and gold primary button — safe for Python via Template."""
 
 
 
31
  tmpl = Template(r"""
32
  :root{
33
- --navy: $navy; --gold: $gold; --ice: $ice; --maroon: $maroon; --amber: $amber;
34
- --text-dark: $text_dark; --text-light: $text_light;
35
-
36
- /* Gradio tokens (force our palette) */
37
- --body-background-fill: var(--navy);
 
 
 
 
 
 
 
 
 
 
 
 
38
  --body-text-color: var(--text-light);
39
- --block-background-fill: rgba(8,61,119,0.82);
40
  --block-title-text-color: var(--text-light);
41
- --border-color-primary: rgba(255,255,255,0.12);
42
 
43
- --button-primary-background-fill: var(--gold);
44
  --button-primary-text-color: var(--text-dark);
45
- --button-primary-border-color: #c89200;
46
-
47
- --button-secondary-background-fill: var(--amber);
48
  --button-secondary-text-color: var(--text-dark);
49
- --button-secondary-border-color: #caa157;
50
 
51
- --link-text-color: var(--amber);
52
  }
53
 
54
- /* Global surfaces & text */
55
- body, .gradio-container{
56
- background: var(--body-background-fill) !important;
57
- color: var(--body-text-color) !important;
 
58
  }
59
 
60
- /* Blocks / tabs */
61
- .gradio-container .block, .gradio-container .tabs, .gradio-container .tabs>.tabitem{
62
- background: var(--block-background-fill) !important;
 
 
63
  color: var(--text-light) !important;
 
64
  border-radius: 12px;
65
- border: 1px solid var(--border-color-primary);
66
  }
67
 
68
- /* Hero stripe using your palette */
69
  #hero{
70
- background: linear-gradient(90deg, var(--navy) 0%, var(--gold) 25%, var(--ice) 45%, var(--maroon) 65%, var(--amber) 85%, transparent 100%);
71
- border: 1px solid rgba(242,180,0,0.6);
72
- border-radius: 14px; padding: 14px 16px; color: var(--text-light);
 
 
 
 
73
  }
74
 
75
- /* KPI chips */
76
- .kpi{ text-align:center; padding:12px; border-radius:10px;
77
- border:1px solid rgba(255,255,255,.14); background: rgba(8,61,119,0.65); color: var(--text-light);}
 
 
 
78
 
79
  /* Buttons */
80
- .gradio-container .gr-button, .gradio-container button{ border-radius:10px !important; font-weight:600 !important; }
 
 
 
81
  .gradio-container .gr-button-primary, .gradio-container button.primary{
82
- background: var(--button-primary-background-fill) !important;
83
- color: var(--button-primary-text-color) !important;
84
  border: 1px solid var(--button-primary-border-color) !important;
 
85
  }
86
  .gradio-container .gr-button-secondary, .gradio-container button.secondary{
87
- background: var(--button-secondary-background-fill) !important;
88
- color: var(--button-secondary-text-color) !important;
89
  border: 1px solid var(--button-secondary-border-color) !important;
90
  }
91
 
92
- /* Inputs */
93
- input, textarea, select, .gr-textbox, .gr-text-area, .gr-dropdown, .gr-file, .gr-slider{
94
- background: rgba(8,61,119,0.55) !important;
 
95
  color: var(--text-light) !important;
96
- border: 1px solid rgba(255,255,255,0.18) !important;
97
  border-radius: 10px !important;
98
  }
99
- input::placeholder, textarea::placeholder{ color: rgba(234,242,255,0.65) !important; }
 
 
 
 
 
 
 
100
 
101
- /* Links & text */
102
- a, .prose a{ color: var(--amber) !important; text-decoration:none; } a:hover{ text-decoration:underline; }
103
- label, .label, .prose h1, .prose h2, .prose h3, .prose p, .markdown-body{ color: var(--text-light) !important; }
104
 
105
- /* Dataframe */
106
- .dataframe, table, .table, .gr-dataframe *{ color: var(--text-light) !important; background: transparent !important; }
107
- .dataframe th{ background: rgba(8,61,119,0.72) !important; border-bottom: 1px solid rgba(255,255,255,0.18) !important; }
108
- .dataframe td{ border-bottom: 1px solid rgba(255,255,255,0.12) !important; }
 
 
 
 
 
 
 
109
 
110
  /* Accordion */
111
  .accordion, .gr-accordion{
112
- background: rgba(8,61,119,0.65) !important; border: 1px solid rgba(255,255,255,0.14) !important; border-radius: 10px !important;
 
 
113
  }
114
 
115
- /* Tabs active underline color */
116
  .gradio-container .tabs .tab-nav button.selected{
117
- box-shadow: inset 0 -3px 0 0 var(--gold) !important; color: var(--text-light) !important;
 
 
 
 
 
 
 
118
  }
119
 
120
- /* Optional: center content */
121
  .gradio-container{ max-width: 1120px; margin: 0 auto; }
122
  """)
123
  return tmpl.substitute(
124
- navy=PALETTE["navy"], gold=PALETTE["gold"], ice=PALETTE["ice"],
125
- maroon=PALETTE["maroon"], amber=PALETTE["amber"],
126
- text_dark=PALETTE["text_on_light"], text_light=PALETTE["text_on_dark"]
 
 
127
  )
128
 
129
  # =========================
@@ -439,7 +506,7 @@ def do_export_docx(question, answer_md, sources_rows):
439
  theme = gr.themes.Soft(primary_hue="indigo", secondary_hue="blue", neutral_hue="slate")
440
 
441
  with gr.Blocks(title=f"{APP_NAME} | RAG over PDFs", theme=theme, css=build_custom_css()) as demo:
442
- # Header / Hero
443
  with gr.Group(elem_id="hero"):
444
  gr.Markdown(f"""
445
  <div style="display:flex;align-items:center;gap:16px;">
@@ -450,13 +517,13 @@ with gr.Blocks(title=f"{APP_NAME} | RAG over PDFs", theme=theme, css=build_custo
450
  Upload your papers, build an index, and ask research questions with verifiable, page-level citations.
451
  </p>""")
452
 
453
- # KPI Row
454
  with gr.Row():
455
  gr.Markdown("**Meaning-aware retrieval**<br><span class='kpi'>E5 + FAISS</span>", elem_classes=["kpi"])
456
  gr.Markdown("**Cited answers**<br><span class='kpi'>Page-level proof</span>", elem_classes=["kpi"])
457
  gr.Markdown("**Runs anywhere**<br><span class='kpi'>HF Spaces or Colab</span>", elem_classes=["kpi"])
458
 
459
- # API Key
460
  with gr.Row():
461
  api_box = gr.Textbox(label="(Optional) Set GROQ_API_KEY", type="password", placeholder="sk_...")
462
  set_btn = gr.Button("Set Key")
@@ -464,13 +531,13 @@ Upload your papers, build an index, and ask research questions with verifiable,
464
  set_btn.click(set_api_key, inputs=[api_box], outputs=[set_out])
465
 
466
  with gr.Tabs():
467
- # Tab 1: Build / Load
468
  with gr.Tab("1) Build or Load Index"):
469
  gr.Markdown("Upload PDFs or a ZIP of PDFs, then click **Build Index**.")
470
  file_u = gr.Files(label="Upload PDFs or ZIP", file_types=[".pdf", ".zip"], type="filepath")
471
  with gr.Row():
472
  build_btn = gr.Button("Build Index", variant="primary")
473
- reload_btn = gr.Button("Reload Saved Index")
474
  download_btn = gr.Button("Download Index (.zip)")
475
  build_out = gr.Markdown()
476
 
@@ -486,7 +553,7 @@ Upload your papers, build an index, and ask research questions with verifiable,
486
  zpath = gr.File(label="Index bundle", interactive=False)
487
  download_btn.click(fn=download_index_zip, outputs=[zpath])
488
 
489
- # Tab 2: Ask
490
  with gr.Tab("2) Ask Questions"):
491
  with gr.Row():
492
  with gr.Column(scale=1):
@@ -498,7 +565,7 @@ Upload your papers, build an index, and ask research questions with verifiable,
498
  temp = gr.Slider(0.0, 1.0, value=0.2, step=0.05, label="Temperature")
499
  with gr.Row():
500
  ask_btn = gr.Button("Answer", variant="primary")
501
- clear_btn = gr.Button("Clear")
502
 
503
  gr.Examples(
504
  examples=[
@@ -523,7 +590,7 @@ Upload your papers, build an index, and ask research questions with verifiable,
523
  export_btn.click(fn=do_export_docx, inputs=[q, ans, src], outputs=[exported])
524
  clear_btn.click(lambda: ("", [], "", gr.update(visible=False)), outputs=[ans, src, snippets_md, export_btn])
525
 
526
- # Tab 3: About
527
  with gr.Tab("About"):
528
  gr.Markdown("""
529
  **ScholarLens** helps researchers move from reading to results with answers grounded in the papers you upload.
 
11
  from string import Template
12
 
13
  # =========================
14
+ # Branding
15
  # =========================
16
  APP_NAME = "ScholarLens"
17
  TAGLINE = "Query your literature, get page-level proof"
18
 
19
+ # =========================
20
+ # Color System (accessible dark theme)
21
+ # =========================
22
+ # Primary palette chosen for high contrast and clear role separation.
23
  PALETTE = {
24
+ "bg": "#0D1224", # deep slate/navy background
25
+ "panel": "#121936", # panel background
26
+ "panel_alt": "#0F1530", # secondary panel
27
+ "text_light":"#EAF0FF", # default light text on dark
28
+ "text_dark": "#0B111C", # text on light surfaces
29
+
30
+ # Accents (all readable on dark):
31
+ "primary": "#22D3EE", # cyan (primary actions)
32
+ "secondary": "#A78BFA", # purple (secondary actions)
33
+ "accent": "#FBBF24", # amber (highlights/links)
34
+ "success": "#34D399", # green (success state)
35
+ "danger": "#FB7185", # rose (errors)
36
+
37
+ # Borders & subtle strokes
38
+ "stroke": "rgba(255,255,255,0.14)",
39
+ "stroke_alt":"rgba(255,255,255,0.10)",
40
  }
41
 
42
  def build_custom_css():
43
+ """
44
+ Strong-contrast dark UI, light text everywhere by default.
45
+ Uses string.Template so CSS braces don't break Python parsing.
46
+ """
47
  tmpl = Template(r"""
48
  :root{
49
+ --bg: $bg;
50
+ --panel: $panel;
51
+ --panel-alt: $panel_alt;
52
+ --text-light: $text_light;
53
+ --text-dark: $text_dark;
54
+
55
+ --primary: $primary;
56
+ --secondary: $secondary;
57
+ --accent: $accent;
58
+ --success: $success;
59
+ --danger: $danger;
60
+
61
+ --stroke: $stroke;
62
+ --stroke-alt: $stroke_alt;
63
+
64
+ /* Feed Gradio's CSS variables so components comply */
65
+ --body-background-fill: var(--bg);
66
  --body-text-color: var(--text-light);
67
+ --block-background-fill: var(--panel);
68
  --block-title-text-color: var(--text-light);
69
+ --border-color-primary: var(--stroke);
70
 
71
+ --button-primary-background-fill: var(--primary);
72
  --button-primary-text-color: var(--text-dark);
73
+ --button-primary-border-color: color-mix(in srgb, var(--primary) 75%, black 25%);
74
+ --button-secondary-background-fill: var(--secondary);
 
75
  --button-secondary-text-color: var(--text-dark);
76
+ --button-secondary-border-color: color-mix(in srgb, var(--secondary) 70%, black 30%);
77
 
78
+ --link-text-color: var(--accent);
79
  }
80
 
81
+ /* Global */
82
+ html, body, .gradio-container{
83
+ background: var(--bg) !important;
84
+ color: var(--text-light) !important;
85
+ font-size: 16px; line-height: 1.5;
86
  }
87
 
88
+ /* Panels / Tabs */
89
+ .gradio-container .block,
90
+ .gradio-container .tabs,
91
+ .gradio-container .tabs > .tabitem{
92
+ background: var(--panel) !important;
93
  color: var(--text-light) !important;
94
+ border: 1px solid var(--stroke);
95
  border-radius: 12px;
 
96
  }
97
 
98
+ /* Hero (subtle gradient from brand accents) */
99
  #hero{
100
+ background:
101
+ radial-gradient(900px 350px at 20% -20%, color-mix(in srgb, var(--secondary) 25%, transparent) 0%, transparent 100%),
102
+ radial-gradient(900px 350px at 120% 10%, color-mix(in srgb, var(--primary) 25%, transparent) 0%, transparent 100%),
103
+ var(--panel-alt);
104
+ border: 1px solid var(--stroke);
105
+ border-radius: 14px; padding: 16px 18px;
106
+ color: var(--text-light);
107
  }
108
 
109
+ /* KPI cards */
110
+ .kpi{
111
+ text-align:center; padding:12px;
112
+ border-radius:10px; border:1px solid var(--stroke);
113
+ background: var(--panel-alt); color: var(--text-light);
114
+ }
115
 
116
  /* Buttons */
117
+ .gradio-container .gr-button, .gradio-container button{
118
+ border-radius: 10px !important; font-weight: 650 !important;
119
+ letter-spacing: .2px;
120
+ }
121
  .gradio-container .gr-button-primary, .gradio-container button.primary{
122
+ background: var(--primary) !important;
123
+ color: var(--text-dark) !important;
124
  border: 1px solid var(--button-primary-border-color) !important;
125
+ box-shadow: 0 8px 20px -8px color-mix(in srgb, var(--primary) 50%, transparent);
126
  }
127
  .gradio-container .gr-button-secondary, .gradio-container button.secondary{
128
+ background: var(--secondary) !important;
129
+ color: var(--text-dark) !important;
130
  border: 1px solid var(--button-secondary-border-color) !important;
131
  }
132
 
133
+ /* Inputs / dropdowns / file */
134
+ input, textarea, select,
135
+ .gr-textbox, .gr-text-area, .gr-dropdown, .gr-file, .gr-slider{
136
+ background: var(--panel-alt) !important;
137
  color: var(--text-light) !important;
138
+ border: 1px solid var(--stroke-alt) !important;
139
  border-radius: 10px !important;
140
  }
141
+ input::placeholder, textarea::placeholder{
142
+ color: color-mix(in srgb, var(--text-light) 60%, transparent) !important;
143
+ }
144
+
145
+ /* Markdown / labels */
146
+ label, .label, .prose h1, .prose h2, .prose h3, .prose p, .markdown-body{
147
+ color: var(--text-light) !important;
148
+ }
149
 
150
+ /* Links */
151
+ a, .prose a{ color: var(--accent) !important; text-decoration:none; }
152
+ a:hover{ text-decoration: underline; }
153
 
154
+ /* Dataframe / tables */
155
+ .dataframe, table, .table, .gr-dataframe *{
156
+ color: var(--text-light) !important; background: transparent !important;
157
+ }
158
+ .dataframe th{
159
+ background: var(--panel-alt) !important;
160
+ border-bottom: 1px solid var(--stroke) !important;
161
+ }
162
+ .dataframe td{
163
+ border-bottom: 1px solid var(--stroke-alt) !important;
164
+ }
165
 
166
  /* Accordion */
167
  .accordion, .gr-accordion{
168
+ background: var(--panel-alt) !important;
169
+ border: 1px solid var(--stroke) !important;
170
+ border-radius: 10px !important;
171
  }
172
 
173
+ /* Tabs active underline */
174
  .gradio-container .tabs .tab-nav button.selected{
175
+ box-shadow: inset 0 -3px 0 0 var(--primary) !important;
176
+ color: var(--text-light) !important;
177
+ }
178
+
179
+ /* Focus outlines for a11y */
180
+ :focus-visible{
181
+ outline: 3px solid var(--accent) !important;
182
+ outline-offset: 2px !important;
183
  }
184
 
185
+ /* Page width for large screens */
186
  .gradio-container{ max-width: 1120px; margin: 0 auto; }
187
  """)
188
  return tmpl.substitute(
189
+ bg=PALETTE["bg"], panel=PALETTE["panel"], panel_alt=PALETTE["panel_alt"],
190
+ text_light=PALETTE["text_light"], text_dark=PALETTE["text_dark"],
191
+ primary=PALETTE["primary"], secondary=PALETTE["secondary"],
192
+ accent=PALETTE["accent"], success=PALETTE["success"], danger=PALETTE["danger"],
193
+ stroke=PALETTE["stroke"], stroke_alt=PALETTE["stroke_alt"],
194
  )
195
 
196
  # =========================
 
506
  theme = gr.themes.Soft(primary_hue="indigo", secondary_hue="blue", neutral_hue="slate")
507
 
508
  with gr.Blocks(title=f"{APP_NAME} | RAG over PDFs", theme=theme, css=build_custom_css()) as demo:
509
+ # Hero
510
  with gr.Group(elem_id="hero"):
511
  gr.Markdown(f"""
512
  <div style="display:flex;align-items:center;gap:16px;">
 
517
  Upload your papers, build an index, and ask research questions with verifiable, page-level citations.
518
  </p>""")
519
 
520
+ # KPIs
521
  with gr.Row():
522
  gr.Markdown("**Meaning-aware retrieval**<br><span class='kpi'>E5 + FAISS</span>", elem_classes=["kpi"])
523
  gr.Markdown("**Cited answers**<br><span class='kpi'>Page-level proof</span>", elem_classes=["kpi"])
524
  gr.Markdown("**Runs anywhere**<br><span class='kpi'>HF Spaces or Colab</span>", elem_classes=["kpi"])
525
 
526
+ # Key
527
  with gr.Row():
528
  api_box = gr.Textbox(label="(Optional) Set GROQ_API_KEY", type="password", placeholder="sk_...")
529
  set_btn = gr.Button("Set Key")
 
531
  set_btn.click(set_api_key, inputs=[api_box], outputs=[set_out])
532
 
533
  with gr.Tabs():
534
+ # Build / Load
535
  with gr.Tab("1) Build or Load Index"):
536
  gr.Markdown("Upload PDFs or a ZIP of PDFs, then click **Build Index**.")
537
  file_u = gr.Files(label="Upload PDFs or ZIP", file_types=[".pdf", ".zip"], type="filepath")
538
  with gr.Row():
539
  build_btn = gr.Button("Build Index", variant="primary")
540
+ reload_btn = gr.Button("Reload Saved Index", variant="secondary")
541
  download_btn = gr.Button("Download Index (.zip)")
542
  build_out = gr.Markdown()
543
 
 
553
  zpath = gr.File(label="Index bundle", interactive=False)
554
  download_btn.click(fn=download_index_zip, outputs=[zpath])
555
 
556
+ # Ask
557
  with gr.Tab("2) Ask Questions"):
558
  with gr.Row():
559
  with gr.Column(scale=1):
 
565
  temp = gr.Slider(0.0, 1.0, value=0.2, step=0.05, label="Temperature")
566
  with gr.Row():
567
  ask_btn = gr.Button("Answer", variant="primary")
568
+ clear_btn = gr.Button("Clear", variant="secondary")
569
 
570
  gr.Examples(
571
  examples=[
 
590
  export_btn.click(fn=do_export_docx, inputs=[q, ans, src], outputs=[exported])
591
  clear_btn.click(lambda: ("", [], "", gr.update(visible=False)), outputs=[ans, src, snippets_md, export_btn])
592
 
593
+ # About
594
  with gr.Tab("About"):
595
  gr.Markdown("""
596
  **ScholarLens** helps researchers move from reading to results with answers grounded in the papers you upload.