pkgprateek commited on
Commit
76c4490
Β·
1 Parent(s): e81fc86

feat(ui): overhaul UI with enterprise glassmorphism and matte theme

Browse files
Files changed (1) hide show
  1. app/main.py +292 -184
app/main.py CHANGED
@@ -75,257 +75,365 @@ class DocumentRagApp:
75
 
76
  app = DocumentRagApp()
77
 
78
- # ChatGPT-inspired dark theme
79
  css = """
 
 
80
  :root {
81
- --bg-dark: #343541;
82
- --bg-darker: #202123;
83
- --bg-input: #40414F;
84
- --text: #ECECF1;
85
- --text-dim: #A0A0AA;
86
- --border: #565869;
87
- --accent: #19C37D;
 
 
 
 
 
 
 
 
 
 
 
88
  }
89
 
90
- .gradio-container {
91
- background: var(--bg-dark) !important;
92
- font-family: -apple-system, system-ui, sans-serif !important;
93
- max-width: 100% !important;
 
 
 
 
 
 
 
94
  padding: 0 !important;
95
  }
96
 
97
- #main-container {
98
- max-width: 800px;
99
- margin: 0 auto;
100
- padding: 2rem 1.5rem;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  }
102
 
103
- /* Header */
 
 
 
 
 
104
  #header {
105
  text-align: center;
106
- margin-bottom: 2rem;
107
- padding-bottom: 1.5rem;
108
- border-bottom: 1px solid var(--border);
109
  }
110
-
111
  #header h1 {
112
- color: var(--text);
113
- font-size: 1.75rem;
114
- font-weight: 600;
115
- margin: 0 0 0.5rem 0;
 
 
116
  }
117
-
118
  #header p {
119
- color: var(--text-dim);
120
- font-size: 0.95rem;
121
- margin: 0;
122
  }
123
 
124
- /* Controls section */
125
- .controls {
126
- background: var(--bg-input);
127
- border-radius: 8px;
128
- padding: 1.25rem;
129
- margin-bottom: 1.5rem;
130
- border: 1px solid var(--border);
 
 
 
 
 
 
131
  }
132
 
133
- .controls-title {
134
- color: var(--text);
135
- font-size: 0.875rem;
136
- font-weight: 600;
137
- margin-bottom: 1rem;
138
  text-transform: uppercase;
139
- letter-spacing: 0.5px;
140
- }
141
-
142
- /* Dropdown and buttons */
143
- select, button, textarea, input {
144
- background: var(--bg-darker) !important;
145
- color: var(--text) !important;
146
- border: 1px solid var(--border) !important;
147
- border-radius: 6px !important;
148
  }
149
 
150
- select:focus, textarea:focus, input:focus {
151
- border-color: var(--accent) !important;
152
- outline: none !important;
 
 
 
153
  }
154
 
155
- button {
156
- padding: 0.625rem 1.25rem !important;
157
- font-weight: 500 !important;
158
- transition: all 0.15s !important;
 
159
  }
160
 
161
- button:hover {
162
- background: var(--bg-input) !important;
163
  border-color: var(--accent) !important;
164
  }
165
 
 
166
  .primary-btn {
167
- background: var(--accent) !important;
168
- color: #000 !important;
 
169
  font-weight: 600 !important;
 
 
 
 
170
  }
171
-
172
  .primary-btn:hover {
173
- background: #1AB370 !important;
 
174
  }
175
 
176
- /* Query buttons */
177
  .query-btn {
178
- width: 100% !important;
 
 
 
 
179
  text-align: left !important;
180
- margin-bottom: 0.5rem !important;
181
  }
182
-
183
- /* Question input */
184
- #question-box {
185
- background: var(--bg-input);
186
- border-radius: 8px;
187
- padding: 1.25rem;
188
- margin-bottom: 1.5rem;
189
- border: 1px solid var(--border);
190
  }
191
 
192
- textarea {
193
- font-size: 1rem !important;
194
- line-height: 1.5 !important;
195
- padding: 0.75rem !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
  }
197
 
198
- /* Answer area */
199
  #answer-section {
200
- background: var(--bg-input);
201
- border-radius: 8px;
202
- padding: 1.5rem;
203
- margin-bottom: 2rem;
204
- border: 1px solid var(--border);
205
- min-height: 300px;
206
  }
207
-
208
  #answer-section .markdown {
209
- color: var(--text) !important;
210
  line-height: 1.7;
211
- font-size: 0.95rem;
212
  }
213
-
214
- /* Footer info */
215
- #footer-info {
216
- max-width: 800px;
217
- margin: 2rem auto 0;
218
- padding: 2rem 1.5rem;
219
- border-top: 1px solid var(--border);
220
  }
221
 
222
- .info-box {
223
- background: var(--bg-input);
224
- border-radius: 6px;
225
- padding: 1rem;
226
- margin-bottom: 1rem;
227
- border: 1px solid var(--border);
228
- font-size: 0.875rem;
229
- color: var(--text-dim);
230
- line-height: 1.6;
231
- }
232
-
233
- .calendly-box {
234
- background: linear-gradient(135deg, #1A7F64, var(--accent));
235
- color: #000;
236
- border-radius: 6px;
237
- padding: 1rem;
238
- text-align: center;
239
  font-weight: 600;
 
 
 
240
  }
241
-
242
- .calendly-box a {
243
- color: #000;
244
- text-decoration: underline;
245
  }
246
  """
247
 
248
  with gr.Blocks(css=css, theme=gr.themes.Base(), title="Enterprise RAG") as demo:
249
  with gr.Column(elem_id="main-container"):
250
- # Header
251
  gr.HTML("""
252
  <div id="header">
253
- <h1>Enterprise RAG Platform</h1>
254
- <p>Document intelligence for Legal, Research, and FinOps</p>
 
 
 
 
 
255
  </div>
256
  """)
257
 
258
- # Load samples
259
- with gr.Group(elem_classes="controls"):
260
- gr.HTML('<div class="controls-title">Load Sample Documents</div>')
261
- with gr.Row():
262
- sample_dropdown = gr.Dropdown(
263
- choices=["Legal", "Research", "FinOps"],
264
- value="Legal",
265
- show_label=False,
266
- scale=3,
267
- )
268
- load_btn = gr.Button("Load", elem_classes="primary-btn", scale=1)
269
- load_status = gr.Markdown("")
270
-
271
- # Upload
272
- with gr.Group(elem_classes="controls"):
273
- gr.HTML('<div class="controls-title">Or Upload Your Documents</div>')
274
- file_upload = gr.File(
275
- file_types=[".pdf", ".docx", ".txt"], show_label=False
276
- )
277
- process_btn = gr.Button("Process", elem_classes="primary-btn")
278
- upload_status = gr.Markdown("")
279
-
280
- # Quick queries
281
- with gr.Group(elem_classes="controls"):
282
- gr.HTML('<div class="controls-title">Quick Queries</div>')
283
- q1 = gr.Button(
284
- "What are the termination conditions?", elem_classes="query-btn"
285
- )
286
- q2 = gr.Button("Summarize payment terms", elem_classes="query-btn")
287
- q3 = gr.Button("What methodology was used?", elem_classes="query-btn")
288
- q4 = gr.Button("Summarize key findings", elem_classes="query-btn")
289
- q5 = gr.Button("Top 3 cost optimizations?", elem_classes="query-btn")
290
- q6 = gr.Button("Extract spend by category", elem_classes="query-btn")
291
-
292
- # Question
293
- with gr.Group(elem_id="question-box"):
294
- gr.HTML('<div class="controls-title">Ask Your Question</div>')
295
- question = gr.Textbox(
296
- placeholder="Type your question here...", show_label=False, lines=2
297
- )
298
- ask_btn = gr.Button("Ask", elem_classes="primary-btn")
299
-
300
- # Answer
301
- with gr.Group(elem_id="answer-section"):
302
- gr.HTML('<div class="controls-title">Answer</div>')
303
- answer = gr.Markdown("*Load documents to get started*")
304
-
305
- # Footer
306
- with gr.Column(elem_id="footer-info"):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
307
  gr.HTML("""
308
- <div class="calendly-box">
309
- πŸ“… 2-Week Paid Pilots Available Β·
310
- <a href="#" target="_blank">Book Discovery Call</a>
311
- </div>
312
- """)
313
- gr.HTML("""
314
- <div class="info-box">
315
- πŸ”’ Privacy: Documents processed locally, auto-deleted after 7 days, never used for training
316
  </div>
317
  """)
318
 
319
- # Event handlers
320
- load_btn.click(fn=app.load_samples, inputs=sample_dropdown, outputs=load_status)
 
 
 
321
  process_btn.click(fn=app.process_file, inputs=file_upload, outputs=upload_status)
322
 
323
- q1.click(fn=lambda: app.ask("What are the termination conditions?"), outputs=answer)
324
- q2.click(fn=lambda: app.ask("Summarize payment terms"), outputs=answer)
325
- q3.click(fn=lambda: app.ask("What methodology was used?"), outputs=answer)
326
- q4.click(fn=lambda: app.ask("Summarize key findings"), outputs=answer)
327
- q5.click(fn=lambda: app.ask("Top 3 cost optimizations?"), outputs=answer)
328
- q6.click(fn=lambda: app.ask("Extract spend by category"), outputs=answer)
 
 
 
 
 
 
 
 
 
 
329
 
330
  ask_btn.click(fn=app.ask, inputs=question, outputs=answer)
331
 
 
75
 
76
  app = DocumentRagApp()
77
 
78
+ # Premium Enterprise Design System (Restored & Cleaned)
79
  css = """
80
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=Outfit:wght@400;500;600;700&display=swap');
81
+
82
  :root {
83
+ /* Brand Palette */
84
+ --primary-gradient: linear-gradient(135deg, #3B82F6 0%, #10B981 100%);
85
+ --surface-dark: #0B0F19;
86
+ --surface-glass: rgba(17, 24, 39, 0.7);
87
+ --border-glass: rgba(255, 255, 255, 0.08);
88
+ --text-primary: #F9FAFB;
89
+ --text-secondary: #9CA3AF;
90
+ --accent: #10B981;
91
+
92
+ --font-heading: 'Outfit', sans-serif;
93
+ --font-body: 'Inter', sans-serif;
94
+ }
95
+
96
+ /* --- GLOBAL RESET & CLEANING --- */
97
+ body, .gradio-container {
98
+ background-color: var(--surface-dark) !important;
99
+ font-family: var(--font-body) !important;
100
+ color: var(--text-primary) !important;
101
  }
102
 
103
+ /* ⚠️ CRITICAL: Remove Gradio's default nested boxes/backgrounds ⚠️ */
104
+ .gradio-container .block,
105
+ .gradio-container .form,
106
+ .gradio-container .gradio-box,
107
+ .gradio-container .padded,
108
+ .gradio-container .gradio-group,
109
+ .gradio-container .gradio-row,
110
+ .gradio-container .gradio-column {
111
+ background-color: transparent !important;
112
+ border: none !important;
113
+ box-shadow: none !important;
114
  padding: 0 !important;
115
  }
116
 
117
+ /* Force transparency on specific internal elements to fix "Grey Box" issue */
118
+ .glass-card div {
119
+ background-color: transparent !important;
120
+ border: none !important;
121
+ }
122
+
123
+ /* Re-assert styles for Inputs/Buttons since the rule above is aggressive */
124
+ .glass-card textarea,
125
+ .glass-card input[type="text"],
126
+ .glass-card .gradio-dropdown {
127
+ background-color: rgba(0, 0, 0, 0.3) !important;
128
+ border: 1px solid var(--border-glass) !important;
129
+ }
130
+
131
+ .glass-card button.primary-btn {
132
+ background: var(--primary-gradient) !important;
133
+ }
134
+
135
+ .glass-card button.query-btn {
136
+ background: rgba(255, 255, 255, 0.05) !important;
137
+ border: 1px solid var(--border-glass) !important;
138
  }
139
 
140
+
141
+ /* Typography */
142
+ h1, h2, h3, h4 { font-family: var(--font-heading); }
143
+ span, p, div { font-family: var(--font-body); }
144
+
145
+ /* --- HERO SECTION --- */
146
  #header {
147
  text-align: center;
148
+ margin-bottom: 4rem;
149
+ padding-top: 2rem;
 
150
  }
 
151
  #header h1 {
152
+ font-size: 3.5rem;
153
+ font-weight: 700;
154
+ margin-bottom: 0.5rem;
155
+ color: #FFFFFF; /* High contrast white */
156
+ text-shadow: 0 0 20px rgba(59, 130, 246, 0.5); /* Glow effect instead of gradient text */
157
+ letter-spacing: -0.02em;
158
  }
 
159
  #header p {
160
+ font-size: 1.2rem;
161
+ color: var(--text-secondary);
 
162
  }
163
 
164
+ /* --- GLASS CARDS --- */
165
+ .glass-card {
166
+ background: var(--surface-glass) !important;
167
+ backdrop-filter: blur(12px);
168
+ -webkit-backdrop-filter: blur(12px);
169
+ border: 1px solid var(--border-glass) !important;
170
+ border-radius: 20px !important;
171
+ padding: 2rem !important; /* Internal padding for the card content */
172
+ margin-bottom: 2rem !important;
173
+ box-shadow: 0 20px 40px -10px rgba(0,0,0,0.5) !important;
174
+ height: 100% !important; /* Attempt to stretch */
175
+ display: flex !important;
176
+ flex-direction: column !important;
177
  }
178
 
179
+ .card-header {
180
+ font-family: var(--font-heading);
181
+ font-size: 0.9rem;
 
 
182
  text-transform: uppercase;
183
+ letter-spacing: 0.1em;
184
+ color: var(--text-secondary);
185
+ margin-bottom: 0.5rem; /* Reduced bottom margin */
186
+ border-bottom: 1px solid var(--border-glass);
187
+ padding-bottom: 0.5rem;
 
 
 
 
188
  }
189
 
190
+ /* --- INPUTS & BUTTONS (Cleaned) --- */
191
+ .gradio-dropdown, .gradio-textbox textarea {
192
+ background-color: rgba(0, 0, 0, 0.3) !important;
193
+ border: 1px solid var(--border-glass) !important;
194
+ border-radius: 10px !important;
195
+ color: var(--text-primary) !important;
196
  }
197
 
198
+ /* Upload Area specific */
199
+ .gradio-file {
200
+ background-color: rgba(0, 0, 0, 0.2) !important;
201
+ border: 2px dashed rgba(255, 255, 255, 0.3) !important; /* Brighter border */
202
+ border-radius: 12px !important;
203
  }
204
 
205
+ .gradio-dropdown:hover, .gradio-textbox textarea:hover {
 
206
  border-color: var(--accent) !important;
207
  }
208
 
209
+ /* Primary Button */
210
  .primary-btn {
211
+ background: var(--primary-gradient) !important;
212
+ border: none !important;
213
+ color: white !important;
214
  font-weight: 600 !important;
215
+ padding: 1rem !important;
216
+ border-radius: 10px !important;
217
+ transition: transform 0.2s;
218
+ box-shadow: 0 4px 15px rgba(16, 185, 129, 0.2);
219
  }
 
220
  .primary-btn:hover {
221
+ transform: translateY(-2px);
222
+ box-shadow: 0 8px 25px rgba(16, 185, 129, 0.3);
223
  }
224
 
225
+ /* Quick Query Buttons */
226
  .query-btn {
227
+ background: rgba(255, 255, 255, 0.05) !important;
228
+ border: 1px solid var(--border-glass) !important;
229
+ color: var(--text-secondary) !important;
230
+ border-radius: 8px !important;
231
+ padding: 0.8rem !important;
232
  text-align: left !important;
233
+ font-size: 0.95rem !important;
234
  }
235
+ .query-btn:hover {
236
+ background: rgba(255, 255, 255, 0.1) !important;
237
+ color: var(--text-primary) !important;
238
+ border-color: var(--accent) !important;
 
 
 
 
239
  }
240
 
241
+ /* --- TABS (Seamless) --- */
242
+ .tab-nav {
243
+ border: none !important;
244
+ margin-top: 1rem !important; /* Spacing above tabs */
245
+ margin-bottom: 1.5rem !important; /* Spacing below tabs */
246
+ background: rgba(0,0,0,0.2) !important;
247
+ border-radius: 12px;
248
+ padding: 4px !important;
249
+ display: flex;
250
+ gap: 4px;
251
+ }
252
+ .tab-nav button {
253
+ border: none !important;
254
+ color: var(--text-secondary) !important;
255
+ background: transparent !important;
256
+ border-radius: 8px !important;
257
+ flex-grow: 1;
258
+ font-family: var(--font-heading) !important;
259
+ }
260
+ .tab-nav button.selected {
261
+ background: rgba(255,255,255,0.1) !important;
262
+ color: var(--text-primary) !important;
263
+ font-weight: 600 !important;
264
  }
265
 
266
+ /* --- ANSWER SECTION --- */
267
  #answer-section {
268
+ background: rgba(0,0,0,0.2) !important;
269
+ border-radius: 12px;
270
+ padding: 1.5rem !important;
271
+ border: 1px solid var(--border-glass);
 
 
272
  }
 
273
  #answer-section .markdown {
274
+ font-size: 1.1rem;
275
  line-height: 1.7;
276
+ color: var(--text-primary);
277
  }
278
+ #answer-section strong {
279
+ color: #60A5FA;
 
 
 
 
 
280
  }
281
 
282
+ /* Footer Badge */
283
+ .calendar-badge {
284
+ background: rgba(16, 185, 129, 0.15);
285
+ color: var(--accent);
286
+ padding: 0.6rem 1.2rem;
287
+ border-radius: 100px;
 
 
 
 
 
 
 
 
 
 
 
288
  font-weight: 600;
289
+ text-decoration: none;
290
+ border: 1px solid rgba(16, 185, 129, 0.3);
291
+ transition: all 0.2s;
292
  }
293
+ .calendar-badge:hover {
294
+ background: rgba(16, 185, 129, 0.25);
295
+ box-shadow: 0 0 20px rgba(16, 185, 129, 0.2);
 
296
  }
297
  """
298
 
299
  with gr.Blocks(css=css, theme=gr.themes.Base(), title="Enterprise RAG") as demo:
300
  with gr.Column(elem_id="main-container"):
301
+ # --- HERO ---
302
  gr.HTML("""
303
  <div id="header">
304
+ <h1>ENTERPRISE RAG PLATFORM</h1>
305
+ <p>Secure, Scalable, Agentic Document Intelligence for the Modern Enterprise.</p>
306
+ <div style="margin-top: 3rem; margin-bottom: 6rem;" id="calendar-button">
307
+ <a href="https://cal.com" target="_blank" class="calendar-badge">
308
+ <span>πŸ“…</span> Book a 30-min Strategy Call
309
+ </a>
310
+ </div>
311
  </div>
312
  """)
313
 
314
+ with gr.Row(equal_height=True): # Force Row to try to equalize height
315
+ # --- LEFT: SETUP CARD ---
316
+ with gr.Column(scale=4):
317
+ with gr.Group(elem_classes="glass-card"):
318
+ gr.Markdown(
319
+ "### SELECT SAMPLE DOCUMENTS", elem_classes="card-header"
320
+ )
321
+ gr.Markdown(
322
+ "<span style='font-size: 0.8rem; opacity: 0.8; margin-bottom: 10px !important;'>_Choose a vertical to load pre-configured samples (Legal, FinOps)_</span>",
323
+ elem_classes="subtitle",
324
+ )
325
+
326
+ # Custom Tabs
327
+ with gr.Tabs():
328
+ with gr.Tab("βš–οΈ Legal"):
329
+ load_legal = gr.Button(
330
+ "Load Legal Samples", elem_classes="primary-btn"
331
+ )
332
+ with gr.Tab("πŸ”¬ Research"):
333
+ load_research = gr.Button(
334
+ "Load Research Samples", elem_classes="primary-btn"
335
+ )
336
+ with gr.Tab("πŸ’° FinOps"):
337
+ load_finops = gr.Button(
338
+ "Load FinOps Samples", elem_classes="primary-btn"
339
+ )
340
+
341
+ load_status = gr.Markdown("", elem_classes="status-message")
342
+
343
+ # Visible Divider - Increased Opacity
344
+ gr.HTML(
345
+ '<div style="margin: 2rem 0; height: 1px; background: rgba(255,255,255,0.3);"></div>'
346
+ )
347
+
348
+ gr.Markdown("### OR UPLOAD FILES", elem_classes="card-header")
349
+ file_upload = gr.File(
350
+ file_types=[".pdf", ".docx", ".txt"],
351
+ show_label=False,
352
+ height=240, # Increased height
353
+ )
354
+
355
+ # Spacer before Process button
356
+ gr.HTML('<div style="height: 1.5rem"></div>')
357
+
358
+ process_btn = gr.Button(
359
+ "Process Documents", elem_classes="primary-btn"
360
+ )
361
+ upload_status = gr.Markdown("")
362
+
363
+ # Spacer to fill height if needed
364
+ gr.HTML('<div style="flex-grow: 1;"></div>')
365
+
366
+ # --- RIGHT: INTERACTION CARD ---
367
+ with gr.Column(scale=6):
368
+ with gr.Group(elem_classes="glass-card"):
369
+ gr.Markdown("### INTELLIGENT ANALYSIS", elem_classes="card-header")
370
+
371
+ # Question Input
372
+ question = gr.Textbox(
373
+ placeholder="Ask anything about your documents (e.g., 'What are the termination conditions?')...",
374
+ show_label=False,
375
+ lines=3,
376
+ elem_classes="gradio-textbox",
377
+ )
378
+
379
+ with gr.Row():
380
+ ask_btn = gr.Button(
381
+ "Analyze & Answer", elem_classes="primary-btn", scale=2
382
+ )
383
+
384
+ # Divider between Analyze and Quick Questions
385
+ gr.HTML(
386
+ '<div style="margin: 2rem 0; height: 1px; background: rgba(255,255,255,0.3);"></div>'
387
+ )
388
+
389
+ gr.Markdown(
390
+ "### QUICK SAMPLE QUESTIONS", elem_classes="card-header"
391
+ )
392
+ with gr.Row():
393
+ q1 = gr.Button("πŸ“‹ Termination Terms", elem_classes="query-btn")
394
+ q2 = gr.Button("πŸ’° Payment Summary", elem_classes="query-btn")
395
+ with gr.Row():
396
+ q3 = gr.Button("πŸ“Š Key Findings", elem_classes="query-btn")
397
+ q4 = gr.Button("⚠️ Risk Analysis", elem_classes="query-btn")
398
+
399
+ # Answer Output
400
+ gr.HTML('<div style="height: 2rem"></div>')
401
+ with gr.Group(elem_id="answer-section"):
402
+ gr.Markdown("### πŸ€– Model Response", elem_classes="card-header")
403
+ answer = gr.Markdown("_AI analysis will appear here..._")
404
+
405
+ # --- FOOTER ---
406
+ with gr.Row(elem_id="footer-info"):
407
  gr.HTML("""
408
+ <div style="text-align: center; color: var(--text-secondary); margin-top: 3rem; padding-bottom: 2rem; font-size: 0.9rem;">
409
+ <p>πŸ”’ <strong>Secure Environment</strong>: Documents processed locally & auto-deleted after 7 days.</p>
410
+ <p style="margin-top: 0.5rem; opacity: 0.6;">Β© 2024 Enterprise RAG Platform. Licensed under MIT.</p>
 
 
 
 
 
411
  </div>
412
  """)
413
 
414
+ # Event Wiring
415
+ load_legal.click(fn=lambda: app.load_samples("Legal"), outputs=load_status)
416
+ load_research.click(fn=lambda: app.load_samples("Research"), outputs=load_status)
417
+ load_finops.click(fn=lambda: app.load_samples("FinOps"), outputs=load_status)
418
+
419
  process_btn.click(fn=app.process_file, inputs=file_upload, outputs=upload_status)
420
 
421
+ q1.click(
422
+ fn=lambda: f"**Query:** Termination Terms\n\n{app.ask('What are the termination conditions?')}",
423
+ outputs=answer,
424
+ )
425
+ q2.click(
426
+ fn=lambda: f"**Query:** Payment Summary\n\n{app.ask('Summarize payment terms')}",
427
+ outputs=answer,
428
+ )
429
+ q3.click(
430
+ fn=lambda: f"**Query:** Key Findings\n\n{app.ask('Summarize key findings')}",
431
+ outputs=answer,
432
+ )
433
+ q4.click(
434
+ fn=lambda: f"**Query:** Risk Analysis\n\n{app.ask('What are the key risks mentioned?')}",
435
+ outputs=answer,
436
+ )
437
 
438
  ask_btn.click(fn=app.ask, inputs=question, outputs=answer)
439