chrisvoncsefalvay commited on
Commit
1e3577a
·
1 Parent(s): 0570cd5

Complete UI redesign with skeuomorphic elements and improved layout

Browse files

- Added header with model author (yasserrmd) and space creator (Chris von Csefalvay) credits
- Added social links (GitHub, X/Twitter, website) in header
- Created skeuomorphic mini model card with gradient effects and shadows
- Built question carousel with 4 categories on right side
- Reorganized layout: chat on left, carousel on right
- Added BibTeX citation boxes for MIRIAD dataset and model
- Implemented clickable question buttons that populate input
- Enhanced visual hierarchy with professional design
- Improved responsive design for mobile/tablet
- Added smooth transitions and hover effects throughout

Files changed (1) hide show
  1. app.py +536 -300
app.py CHANGED
@@ -107,332 +107,617 @@ def generate_response(
107
 
108
  return response
109
 
110
- # Categorised example questions for better showcase
111
- EXAMPLE_CATEGORIES = {
112
- "Patient Education": [
113
  "What are the main types of dental cavities and how can I prevent them?",
114
  "Explain the stages of gum disease from gingivitis to periodontitis",
115
- "What should I expect during my first dental cleaning appointment?",
116
  ],
117
- "Treatment Procedures": [
118
  "Walk me through the steps of a root canal treatment",
119
  "What's the difference between a crown and a veneer?",
120
- "How does the dental implant process work from start to finish?",
121
  ],
122
- "Oral Health & Prevention": [
123
  "What's the proper brushing technique for optimal plaque removal?",
124
  "How does fluoride protect teeth and is it safe for children?",
125
- "What foods should I avoid to maintain healthy teeth?",
126
  ],
127
- "Paediatric Dentistry": [
128
- "When should a child have their first dental visit?",
129
- "Explain the tooth eruption timeline in children",
130
- "How can parents help prevent early childhood cavities?",
131
- ],
132
- "Emergency & Post-Care": [
133
- "What should I do if I knock out a permanent tooth?",
134
- "How should I care for my mouth after wisdom tooth extraction?",
135
- "What are signs of a dental infection that needs immediate attention?",
136
  ]
137
  }
138
 
139
- # Flatten examples for the Examples component
140
- EXAMPLES = []
141
- for category, questions in EXAMPLE_CATEGORIES.items():
142
- for question in questions:
143
- EXAMPLES.append([question])
144
-
145
- # Custom CSS for improved styling with proper dark mode support
146
  custom_css = """
147
- /* Improved disclaimer box with proper dark mode support */
148
- .disclaimer-box {
149
- background: linear-gradient(135deg, #fff9e6 0%, #fff3cd 100%);
150
- border: 2px solid #f0ad4e;
151
- border-radius: 10px;
152
- padding: 16px 20px;
153
- margin: 20px 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154
  font-size: 14px;
155
- line-height: 1.6;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
  position: relative;
157
  overflow: hidden;
158
  }
159
 
160
- /* Dark mode disclaimer */
161
- .dark .disclaimer-box {
162
- background: linear-gradient(135deg, #3d2f1f 0%, #4a3a28 100%);
163
- border: 2px solid #d4a574;
164
- color: #ffd9b3;
 
165
  }
166
 
167
- .disclaimer-box::before {
168
  content: '';
169
  position: absolute;
170
- left: 0;
171
  top: 0;
172
- bottom: 0;
173
- width: 4px;
174
- background: #f0ad4e;
175
- }
176
-
177
- .dark .disclaimer-box::before {
178
- background: #d4a574;
179
  }
180
 
181
- .disclaimer-title {
182
- font-weight: 600;
183
- color: #d58512;
184
- margin-bottom: 8px;
 
185
  display: flex;
186
  align-items: center;
187
  gap: 8px;
188
  }
189
 
190
- .dark .disclaimer-title {
191
- color: #ffa500;
192
  }
193
 
194
- .disclaimer-text {
195
- color: #856404;
 
 
 
196
  }
197
 
198
- .dark .disclaimer-text {
199
- color: #ffd9b3;
 
 
 
 
200
  }
201
 
202
- /* Model capabilities cards */
203
- .capability-cards {
204
- display: grid;
205
- grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
206
- gap: 16px;
207
- margin: 20px 0;
208
  }
209
 
210
- .capability-card {
211
- background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
212
- border: 1px solid #dee2e6;
213
- border-radius: 8px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
214
  padding: 16px;
 
 
 
 
215
  transition: transform 0.2s, box-shadow 0.2s;
216
  }
217
 
218
- .dark .capability-card {
219
- background: linear-gradient(135deg, #2b2b2b 0%, #1f1f1f 100%);
220
- border: 1px solid #404040;
 
 
 
221
  }
222
 
223
- .capability-card:hover {
224
  transform: translateY(-2px);
225
- box-shadow: 0 4px 12px rgba(0,0,0,0.1);
 
 
226
  }
227
 
228
- .dark .capability-card:hover {
229
- box-shadow: 0 4px 12px rgba(255,255,255,0.1);
 
 
230
  }
231
 
232
- .capability-title {
233
  font-weight: 600;
234
- color: #495057;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
  margin-bottom: 8px;
236
- font-size: 16px;
 
 
 
 
 
237
  }
238
 
239
- .dark .capability-title {
240
- color: #e9ecef;
 
 
241
  }
242
 
243
- .capability-description {
244
- color: #6c757d;
245
- font-size: 14px;
246
- line-height: 1.5;
 
 
247
  }
248
 
249
- .dark .capability-description {
250
- color: #adb5bd;
251
  }
252
 
253
- /* Stats badges */
254
- .stats-container {
255
- display: flex;
256
- gap: 16px;
257
- flex-wrap: wrap;
258
- margin: 16px 0;
259
  }
260
 
261
- .stat-badge {
262
- background: linear-gradient(135deg, #e7f3ff 0%, #cfe2ff 100%);
263
- border: 1px solid #b6d4fe;
264
- border-radius: 20px;
265
- padding: 8px 16px;
266
- display: flex;
267
- align-items: center;
268
- gap: 8px;
269
  }
270
 
271
- .dark .stat-badge {
272
- background: linear-gradient(135deg, #1a3a52 0%, #0f2940 100%);
273
- border: 1px solid #2563eb;
 
 
 
 
 
 
274
  }
275
 
276
- .stat-label {
277
- color: #0066cc;
278
- font-weight: 500;
279
- font-size: 12px;
280
- text-transform: uppercase;
281
- letter-spacing: 0.5px;
282
  }
283
 
284
- .dark .stat-label {
285
- color: #60a5fa;
 
 
 
286
  }
287
 
288
- .stat-value {
289
- color: #004099;
 
 
 
 
290
  font-weight: 700;
291
- font-size: 14px;
 
 
292
  }
293
 
294
- .dark .stat-value {
295
- color: #93bbfc;
296
  }
297
 
298
- /* Improved button styling */
299
- .gr-button-primary {
300
- background: linear-gradient(135deg, #0066cc 0%, #0052a3 100%) !important;
301
- border: none !important;
302
- color: white !important;
303
- font-weight: 600 !important;
304
- transition: all 0.3s ease !important;
305
  }
306
 
307
- .gr-button-primary:hover {
308
- background: linear-gradient(135deg, #0052a3 0%, #003d7a 100%) !important;
309
- transform: translateY(-1px);
310
- box-shadow: 0 4px 12px rgba(0, 102, 204, 0.3);
 
 
 
 
311
  }
312
 
313
- /* Chat improvements */
314
- .gr-chatbot {
315
- border-radius: 12px !important;
316
- border: 1px solid #dee2e6 !important;
 
 
317
  }
318
 
319
- .dark .gr-chatbot {
320
- border: 1px solid #404040 !important;
 
 
 
321
  }
322
 
323
- /* Example section styling */
324
- .example-category {
325
- margin-bottom: 12px;
 
 
 
 
326
  padding: 12px;
327
- background: #f8f9fa;
328
  border-radius: 8px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
329
  }
330
 
331
- .dark .example-category {
332
- background: #1f1f1f;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
333
  }
334
 
335
- .example-category-title {
336
  font-weight: 600;
337
- color: #495057;
338
  margin-bottom: 8px;
339
- font-size: 14px;
340
- text-transform: uppercase;
341
- letter-spacing: 0.5px;
 
342
  }
343
 
344
- .dark .example-category-title {
345
- color: #e9ecef;
346
  }
347
 
348
- /* Header styling */
349
- .main-header {
350
- background: linear-gradient(135deg, #0066cc 0%, #0052a3 100%);
351
- color: white;
352
- padding: 32px;
353
- border-radius: 12px;
354
- margin-bottom: 24px;
355
- text-align: center;
356
  }
357
 
358
- .dark .main-header {
359
- background: linear-gradient(135deg, #1e3a8a 0%, #1e40af 100%);
360
  }
361
 
362
- .header-title {
363
- font-size: 36px;
364
- font-weight: 700;
365
- margin-bottom: 12px;
 
366
  }
367
 
368
- .header-subtitle {
369
- font-size: 18px;
370
- opacity: 0.95;
371
- font-weight: 400;
 
 
 
 
 
 
 
372
  }
373
 
374
- /* Mobile responsiveness */
375
  @media (max-width: 768px) {
376
- .capability-cards {
377
- grid-template-columns: 1fr;
378
- }
379
-
380
- .stats-container {
381
- flex-direction: column;
382
  }
383
 
384
- .stat-badge {
385
- width: 100%;
386
- justify-content: center;
387
  }
388
 
389
- .header-title {
390
- font-size: 28px;
391
  }
392
 
393
- .header-subtitle {
394
- font-size: 16px;
395
  }
396
  }
397
  """
398
 
399
- # Create Gradio interface with improved design
400
- with gr.Blocks(theme=gr.themes.Soft(), css=custom_css) as demo:
401
- # Professional header with gradient
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
402
  gr.HTML(
403
  """
404
- <div class="main-header">
405
  <h1 class="header-title">🦷 DentaInstruct-1.2B Demo</h1>
406
  <p class="header-subtitle">Advanced AI assistant for dental education and oral health information</p>
 
 
 
 
 
 
 
 
 
407
  </div>
408
  """
409
  )
410
 
411
- # Model statistics and capabilities
412
  gr.HTML(
413
  """
414
- <div class="stats-container">
415
- <div class="stat-badge">
416
- <span class="stat-label">Model Size</span>
417
- <span class="stat-value">1.17B params</span>
418
  </div>
419
- <div class="stat-badge">
420
- <span class="stat-label">Base Model</span>
421
- <span class="stat-value">LFM2-1.2B</span>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
422
  </div>
423
- <div class="stat-badge">
424
- <span class="stat-label">Training Data</span>
425
- <span class="stat-value">MIRIAD Dental</span>
426
- </div>
427
- <div class="stat-badge">
428
- <span class="stat-label">Response Time</span>
429
- <span class="stat-value">< 2 seconds</span>
430
  </div>
431
  </div>
432
  """
433
  )
434
 
435
- # Improved disclaimer with better visibility
436
  gr.HTML(
437
  """
438
  <div class="disclaimer-box">
@@ -448,42 +733,10 @@ with gr.Blocks(theme=gr.themes.Soft(), css=custom_css) as demo:
448
  """
449
  )
450
 
451
- # Model capabilities showcase
452
- gr.HTML(
453
- """
454
- <h2 style="margin-top: 24px; margin-bottom: 16px;">What can DentaInstruct help you with?</h2>
455
- <div class="capability-cards">
456
- <div class="capability-card">
457
- <div class="capability-title">📚 Patient Education</div>
458
- <div class="capability-description">Clear explanations of dental conditions, treatments, and procedures in patient-friendly language</div>
459
- </div>
460
- <div class="capability-card">
461
- <div class="capability-title">🔍 Procedure Details</div>
462
- <div class="capability-description">Step-by-step breakdowns of common dental procedures from cleanings to complex treatments</div>
463
- </div>
464
- <div class="capability-card">
465
- <div class="capability-title">🛡️ Prevention Tips</div>
466
- <div class="capability-description">Evidence-based oral hygiene guidance and preventive care recommendations</div>
467
- </div>
468
- <div class="capability-card">
469
- <div class="capability-title">👶 Paediatric Dentistry</div>
470
- <div class="capability-description">Specialised information about children's dental development and care</div>
471
- </div>
472
- <div class="capability-card">
473
- <div class="capability-title">🚨 Emergency Guidance</div>
474
- <div class="capability-description">Educational information about dental emergencies and post-treatment care</div>
475
- </div>
476
- <div class="capability-card">
477
- <div class="capability-title">🦷 Anatomy & Terms</div>
478
- <div class="capability-description">Detailed explanations of dental anatomy and professional terminology</div>
479
- </div>
480
- </div>
481
- """
482
- )
483
-
484
- # Main chat interface
485
- with gr.Row():
486
- with gr.Column(scale=1):
487
  chatbot = gr.Chatbot(
488
  height=500,
489
  label="Dental Education Assistant",
@@ -505,9 +758,31 @@ with gr.Blocks(theme=gr.themes.Soft(), css=custom_css) as demo:
505
  with gr.Row():
506
  submit = gr.Button("Send Question", variant="primary", scale=1)
507
  clear = gr.Button("Clear Chat", scale=1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
508
 
509
- # Advanced settings in a collapsible section
510
- with gr.Accordion("⚙️ Advanced Settings", open=False):
511
  with gr.Row():
512
  with gr.Column(scale=1):
513
  temperature = gr.Slider(
@@ -547,73 +822,34 @@ with gr.Blocks(theme=gr.themes.Soft(), css=custom_css) as demo:
547
  info="Reduces repetitive phrases in responses"
548
  )
549
 
550
- # Example questions organised by category
551
- with gr.Accordion("💡 Example Questions by Category", open=True):
552
- gr.Examples(
553
- examples=EXAMPLES[:8], # Show first 8 examples
554
- inputs=msg,
555
- label="Quick Start Examples",
556
- )
557
-
558
- # Additional categorised examples
559
- gr.Markdown(
560
- """
561
- ### More Example Categories:
562
- - **Patient Education**: Understanding conditions, prevention, and treatment basics
563
- - **Treatment Procedures**: Detailed explanations of dental procedures
564
- - **Oral Health & Prevention**: Daily care and preventive measures
565
- - **Paediatric Dentistry**: Children's dental health and development
566
- - **Emergency & Post-Care**: Urgent situations and aftercare instructions
567
- """
568
- )
569
-
570
- # About section with professional information
571
- gr.Markdown(
572
  """
573
- ---
574
-
575
- ## About DentaInstruct-1.2B
576
-
577
- DentaInstruct-1.2B is a specialised language model fine-tuned specifically for dental education and oral health information.
578
- Built on the efficient LFM2-1.2B architecture, it combines compact size with domain expertise to provide accurate,
579
- educational content about dentistry.
580
-
581
- ### Key Features:
582
- - **Specialised Training**: Fine-tuned on comprehensive dental educational content from the MIRIAD dataset
583
- - **Efficient Architecture**: 1.17B parameters optimised for fast response times
584
- - **Broad Coverage**: Knowledgeable about general dentistry, orthodontics, periodontics, endodontics, and more
585
- - **Educational Focus**: Designed to explain complex dental concepts in accessible language
586
- - **Multi-context Support**: Can handle patient education, professional discussions, and academic queries
587
-
588
- ### Technical Specifications:
589
- - **Architecture**: Transformer-based language model
590
- - **Base Model**: LiquidAI LFM2-1.2B
591
- - **Training Method**: Supervised fine-tuning on dental domain data
592
- - **Context Length**: 2048 tokens
593
- - **Inference**: Optimised for GPU acceleration with bfloat16 precision
594
-
595
- ### Use Cases:
596
- - Patient education materials and explanations
597
- - Dental student study assistance
598
- - Quick reference for dental terminology
599
- - Understanding treatment options and procedures
600
- - Oral health and hygiene guidance
601
-
602
- ### Important Considerations:
603
- - This model is for educational purposes only
604
- - Not intended for clinical decision-making
605
- - Information should be verified with professional sources
606
- - Always consult qualified dental professionals for personal health concerns
607
-
608
- ---
609
-
610
- **Model Creator**: [@yasserrmd](https://huggingface.co/yasserrmd) |
611
- **Space Developer**: [@chrisvoncsefalvay](https://huggingface.co/chrisvoncsefalvay) |
612
- **License**: Apache 2.0
613
-
614
- 🔗 [Model Card](https://huggingface.co/yasserrmd/DentaInstruct-1.2B) |
615
- 📊 [MIRIAD Dataset](https://huggingface.co/datasets/miriad) |
616
- 💬 [Report Issues](https://huggingface.co/spaces/chrisvoncsefalvay/dental-vqa-comparison/discussions)
617
  """
618
  )
619
 
 
107
 
108
  return response
109
 
110
+ # Question categories for the carousel
111
+ QUESTION_CATEGORIES = {
112
+ "Patient education": [
113
  "What are the main types of dental cavities and how can I prevent them?",
114
  "Explain the stages of gum disease from gingivitis to periodontitis",
115
+ "What should I expect during my first dental cleaning appointment?"
116
  ],
117
+ "Procedures": [
118
  "Walk me through the steps of a root canal treatment",
119
  "What's the difference between a crown and a veneer?",
120
+ "How does the dental implant process work from start to finish?"
121
  ],
122
+ "Preventative care advice": [
123
  "What's the proper brushing technique for optimal plaque removal?",
124
  "How does fluoride protect teeth and is it safe for children?",
125
+ "What foods should I avoid to maintain healthy teeth?"
126
  ],
127
+ "Anatomy and terms": [
128
+ "Explain the anatomy of a tooth from crown to root",
129
+ "What are the different types of teeth and their functions?",
130
+ "What is the difference between enamel, dentin, and pulp?"
 
 
 
 
 
131
  ]
132
  }
133
 
134
+ # Custom CSS for the redesigned interface
 
 
 
 
 
 
135
  custom_css = """
136
+ /* Reset and base styles */
137
+ * {
138
+ box-sizing: border-box;
139
+ }
140
+
141
+ /* Header with credits */
142
+ .header-container {
143
+ background: linear-gradient(135deg, #1e40af 0%, #3b82f6 50%, #60a5fa 100%);
144
+ border-radius: 16px;
145
+ padding: 32px;
146
+ margin-bottom: 24px;
147
+ color: white;
148
+ text-align: center;
149
+ box-shadow: 0 8px 32px rgba(30, 64, 175, 0.3);
150
+ }
151
+
152
+ .dark .header-container {
153
+ background: linear-gradient(135deg, #1e3a8a 0%, #3730a3 50%, #4338ca 100%);
154
+ }
155
+
156
+ .header-title {
157
+ font-size: 40px;
158
+ font-weight: 800;
159
+ margin-bottom: 8px;
160
+ text-shadow: 0 2px 4px rgba(0,0,0,0.1);
161
+ }
162
+
163
+ .header-subtitle {
164
+ font-size: 18px;
165
+ opacity: 0.95;
166
+ margin-bottom: 16px;
167
+ }
168
+
169
+ .header-credits {
170
  font-size: 14px;
171
+ opacity: 0.9;
172
+ margin-bottom: 12px;
173
+ }
174
+
175
+ .header-credits a {
176
+ color: #fef3c7;
177
+ text-decoration: none;
178
+ font-weight: 500;
179
+ }
180
+
181
+ .header-credits a:hover {
182
+ color: #fde68a;
183
+ text-decoration: underline;
184
+ }
185
+
186
+ .social-links {
187
+ display: flex;
188
+ justify-content: center;
189
+ gap: 16px;
190
+ margin-top: 12px;
191
+ }
192
+
193
+ .social-link {
194
+ color: #e0e7ff;
195
+ text-decoration: none;
196
+ font-size: 14px;
197
+ padding: 4px 8px;
198
+ border-radius: 6px;
199
+ transition: all 0.2s;
200
+ }
201
+
202
+ .social-link:hover {
203
+ background: rgba(255,255,255,0.1);
204
+ color: white;
205
+ }
206
+
207
+ /* Mini model card - skeuomorphic design */
208
+ .model-card {
209
+ background: linear-gradient(145deg, #f8fafc 0%, #e2e8f0 100%);
210
+ border: 1px solid #cbd5e1;
211
+ border-radius: 16px;
212
+ padding: 20px;
213
+ margin-bottom: 24px;
214
+ box-shadow:
215
+ 0 10px 25px rgba(0,0,0,0.1),
216
+ inset 0 1px 0 rgba(255,255,255,0.6);
217
  position: relative;
218
  overflow: hidden;
219
  }
220
 
221
+ .dark .model-card {
222
+ background: linear-gradient(145deg, #374151 0%, #1f2937 100%);
223
+ border: 1px solid #4b5563;
224
+ box-shadow:
225
+ 0 10px 25px rgba(0,0,0,0.3),
226
+ inset 0 1px 0 rgba(255,255,255,0.1);
227
  }
228
 
229
+ .model-card::before {
230
  content: '';
231
  position: absolute;
 
232
  top: 0;
233
+ left: 0;
234
+ right: 0;
235
+ height: 2px;
236
+ background: linear-gradient(90deg, #3b82f6, #8b5cf6, #ef4444, #f59e0b);
 
 
 
237
  }
238
 
239
+ .model-card-title {
240
+ font-size: 20px;
241
+ font-weight: 700;
242
+ color: #1e293b;
243
+ margin-bottom: 12px;
244
  display: flex;
245
  align-items: center;
246
  gap: 8px;
247
  }
248
 
249
+ .dark .model-card-title {
250
+ color: #f1f5f9;
251
  }
252
 
253
+ .model-stats {
254
+ display: grid;
255
+ grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
256
+ gap: 12px;
257
+ margin-bottom: 16px;
258
  }
259
 
260
+ .model-stat {
261
+ background: rgba(59, 130, 246, 0.1);
262
+ border: 1px solid rgba(59, 130, 246, 0.2);
263
+ border-radius: 8px;
264
+ padding: 8px 12px;
265
+ text-align: center;
266
  }
267
 
268
+ .dark .model-stat {
269
+ background: rgba(59, 130, 246, 0.15);
270
+ border: 1px solid rgba(59, 130, 246, 0.3);
 
 
 
271
  }
272
 
273
+ .stat-value {
274
+ font-weight: 700;
275
+ font-size: 14px;
276
+ color: #3b82f6;
277
+ }
278
+
279
+ .dark .stat-value {
280
+ color: #60a5fa;
281
+ }
282
+
283
+ .stat-label {
284
+ font-size: 11px;
285
+ color: #64748b;
286
+ text-transform: uppercase;
287
+ letter-spacing: 0.5px;
288
+ margin-top: 2px;
289
+ }
290
+
291
+ .dark .stat-label {
292
+ color: #94a3b8;
293
+ }
294
+
295
+ .model-description {
296
+ color: #475569;
297
+ font-size: 14px;
298
+ line-height: 1.6;
299
+ }
300
+
301
+ .dark .model-description {
302
+ color: #cbd5e1;
303
+ }
304
+
305
+ /* Question carousel - right side */
306
+ .question-carousel {
307
+ background: linear-gradient(145deg, #ffffff 0%, #f1f5f9 100%);
308
+ border: 1px solid #e2e8f0;
309
+ border-radius: 16px;
310
+ padding: 20px;
311
+ box-shadow:
312
+ 0 4px 16px rgba(0,0,0,0.08),
313
+ inset 0 1px 0 rgba(255,255,255,0.8);
314
+ height: fit-content;
315
+ position: sticky;
316
+ top: 20px;
317
+ }
318
+
319
+ .dark .question-carousel {
320
+ background: linear-gradient(145deg, #1f2937 0%, #111827 100%);
321
+ border: 1px solid #374151;
322
+ box-shadow:
323
+ 0 4px 16px rgba(0,0,0,0.2),
324
+ inset 0 1px 0 rgba(255,255,255,0.05);
325
+ }
326
+
327
+ .carousel-title {
328
+ font-size: 18px;
329
+ font-weight: 700;
330
+ color: #1e293b;
331
+ margin-bottom: 16px;
332
+ text-align: center;
333
+ }
334
+
335
+ .dark .carousel-title {
336
+ color: #f1f5f9;
337
+ }
338
+
339
+ .carousel-card {
340
+ background: linear-gradient(135deg, #fafafa 0%, #f4f4f5 100%);
341
+ border: 1px solid #e4e4e7;
342
+ border-radius: 12px;
343
  padding: 16px;
344
+ margin-bottom: 16px;
345
+ box-shadow:
346
+ 0 2px 8px rgba(0,0,0,0.06),
347
+ inset 0 1px 0 rgba(255,255,255,0.7);
348
  transition: transform 0.2s, box-shadow 0.2s;
349
  }
350
 
351
+ .dark .carousel-card {
352
+ background: linear-gradient(135deg, #374151 0%, #2d3748 100%);
353
+ border: 1px solid #4b5563;
354
+ box-shadow:
355
+ 0 2px 8px rgba(0,0,0,0.15),
356
+ inset 0 1px 0 rgba(255,255,255,0.05);
357
  }
358
 
359
+ .carousel-card:hover {
360
  transform: translateY(-2px);
361
+ box-shadow:
362
+ 0 4px 16px rgba(0,0,0,0.12),
363
+ inset 0 1px 0 rgba(255,255,255,0.7);
364
  }
365
 
366
+ .dark .carousel-card:hover {
367
+ box-shadow:
368
+ 0 4px 16px rgba(0,0,0,0.25),
369
+ inset 0 1px 0 rgba(255,255,255,0.05);
370
  }
371
 
372
+ .carousel-card-title {
373
  font-weight: 600;
374
+ color: #3b82f6;
375
+ margin-bottom: 12px;
376
+ font-size: 15px;
377
+ }
378
+
379
+ .dark .carousel-card-title {
380
+ color: #60a5fa;
381
+ }
382
+
383
+ .question-button {
384
+ display: block;
385
+ width: 100%;
386
+ background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
387
+ border: 1px solid #cbd5e1;
388
+ border-radius: 8px;
389
+ padding: 8px 12px;
390
  margin-bottom: 8px;
391
+ font-size: 13px;
392
+ color: #475569;
393
+ text-align: left;
394
+ cursor: pointer;
395
+ transition: all 0.2s;
396
+ box-shadow: 0 1px 3px rgba(0,0,0,0.05);
397
  }
398
 
399
+ .dark .question-button {
400
+ background: linear-gradient(135deg, #4b5563 0%, #374151 100%);
401
+ border: 1px solid #6b7280;
402
+ color: #d1d5db;
403
  }
404
 
405
+ .question-button:hover {
406
+ background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
407
+ color: white;
408
+ border-color: #3b82f6;
409
+ transform: translateY(-1px);
410
+ box-shadow: 0 2px 8px rgba(59, 130, 246, 0.3);
411
  }
412
 
413
+ .question-button:last-child {
414
+ margin-bottom: 0;
415
  }
416
 
417
+ /* Main layout */
418
+ .main-layout {
419
+ display: grid;
420
+ grid-template-columns: 2fr 1fr;
421
+ gap: 24px;
422
+ margin-bottom: 24px;
423
  }
424
 
425
+ @media (max-width: 1024px) {
426
+ .main-layout {
427
+ grid-template-columns: 1fr;
428
+ }
429
+
430
+ .question-carousel {
431
+ position: static;
432
+ }
433
  }
434
 
435
+ /* Chat interface improvements */
436
+ .chat-container {
437
+ background: linear-gradient(145deg, #ffffff 0%, #f8fafc 100%);
438
+ border: 1px solid #e2e8f0;
439
+ border-radius: 16px;
440
+ padding: 20px;
441
+ box-shadow:
442
+ 0 4px 16px rgba(0,0,0,0.08),
443
+ inset 0 1px 0 rgba(255,255,255,0.8);
444
  }
445
 
446
+ .dark .chat-container {
447
+ background: linear-gradient(145deg, #1f2937 0%, #111827 100%);
448
+ border: 1px solid #374151;
449
+ box-shadow:
450
+ 0 4px 16px rgba(0,0,0,0.2),
451
+ inset 0 1px 0 rgba(255,255,255,0.05);
452
  }
453
 
454
+ /* Citation boxes */
455
+ .citation-section {
456
+ margin-top: 32px;
457
+ padding-top: 24px;
458
+ border-top: 2px solid #e2e8f0;
459
  }
460
 
461
+ .dark .citation-section {
462
+ border-top: 2px solid #374151;
463
+ }
464
+
465
+ .citation-title {
466
+ font-size: 20px;
467
  font-weight: 700;
468
+ color: #1e293b;
469
+ margin-bottom: 16px;
470
+ text-align: center;
471
  }
472
 
473
+ .dark .citation-title {
474
+ color: #f1f5f9;
475
  }
476
 
477
+ .citation-boxes {
478
+ display: grid;
479
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
480
+ gap: 16px;
 
 
 
481
  }
482
 
483
+ .citation-box {
484
+ background: linear-gradient(145deg, #f8fafc 0%, #e2e8f0 100%);
485
+ border: 1px solid #cbd5e1;
486
+ border-radius: 12px;
487
+ padding: 16px;
488
+ box-shadow:
489
+ 0 4px 12px rgba(0,0,0,0.08),
490
+ inset 0 1px 0 rgba(255,255,255,0.6);
491
  }
492
 
493
+ .dark .citation-box {
494
+ background: linear-gradient(145deg, #374151 0%, #1f2937 100%);
495
+ border: 1px solid #4b5563;
496
+ box-shadow:
497
+ 0 4px 12px rgba(0,0,0,0.2),
498
+ inset 0 1px 0 rgba(255,255,255,0.1);
499
  }
500
 
501
+ .citation-box h4 {
502
+ color: #3b82f6;
503
+ font-weight: 600;
504
+ margin-bottom: 8px;
505
+ font-size: 16px;
506
  }
507
 
508
+ .dark .citation-box h4 {
509
+ color: #60a5fa;
510
+ }
511
+
512
+ .citation-content {
513
+ background: #1f2937;
514
+ color: #e5e7eb;
515
  padding: 12px;
 
516
  border-radius: 8px;
517
+ font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
518
+ font-size: 12px;
519
+ line-height: 1.4;
520
+ overflow-x: auto;
521
+ white-space: pre-wrap;
522
+ word-break: break-all;
523
+ margin-top: 8px;
524
+ }
525
+
526
+ .dark .citation-content {
527
+ background: #111827;
528
+ border: 1px solid #374151;
529
+ }
530
+
531
+ /* Advanced settings styling */
532
+ .advanced-settings {
533
+ background: linear-gradient(145deg, #f1f5f9 0%, #e2e8f0 100%);
534
+ border: 1px solid #cbd5e1;
535
+ border-radius: 12px;
536
+ margin: 16px 0;
537
+ box-shadow:
538
+ 0 2px 8px rgba(0,0,0,0.06),
539
+ inset 0 1px 0 rgba(255,255,255,0.7);
540
+ }
541
+
542
+ .dark .advanced-settings {
543
+ background: linear-gradient(145deg, #374151 0%, #1f2937 100%);
544
+ border: 1px solid #4b5563;
545
+ box-shadow:
546
+ 0 2px 8px rgba(0,0,0,0.15),
547
+ inset 0 1px 0 rgba(255,255,255,0.05);
548
  }
549
 
550
+ /* Disclaimer styling */
551
+ .disclaimer-box {
552
+ background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);
553
+ border: 2px solid #f59e0b;
554
+ border-radius: 12px;
555
+ padding: 16px 20px;
556
+ margin: 20px 0;
557
+ box-shadow:
558
+ 0 4px 12px rgba(245, 158, 11, 0.2),
559
+ inset 0 1px 0 rgba(255,255,255,0.5);
560
+ position: relative;
561
+ }
562
+
563
+ .dark .disclaimer-box {
564
+ background: linear-gradient(135deg, #92400e 0%, #78350f 100%);
565
+ border: 2px solid #f59e0b;
566
+ color: #fef3c7;
567
+ box-shadow:
568
+ 0 4px 12px rgba(245, 158, 11, 0.3),
569
+ inset 0 1px 0 rgba(255,255,255,0.1);
570
+ }
571
+
572
+ .disclaimer-box::before {
573
+ content: '';
574
+ position: absolute;
575
+ left: 0;
576
+ top: 0;
577
+ bottom: 0;
578
+ width: 4px;
579
+ background: #f59e0b;
580
+ border-radius: 2px 0 0 2px;
581
  }
582
 
583
+ .disclaimer-title {
584
  font-weight: 600;
585
+ color: #92400e;
586
  margin-bottom: 8px;
587
+ display: flex;
588
+ align-items: center;
589
+ gap: 8px;
590
+ font-size: 15px;
591
  }
592
 
593
+ .dark .disclaimer-title {
594
+ color: #fbbf24;
595
  }
596
 
597
+ .disclaimer-text {
598
+ color: #78350f;
599
+ font-size: 14px;
600
+ line-height: 1.5;
 
 
 
 
601
  }
602
 
603
+ .dark .disclaimer-text {
604
+ color: #fef3c7;
605
  }
606
 
607
+ /* Button improvements */
608
+ .gr-button {
609
+ border-radius: 8px !important;
610
+ font-weight: 600 !important;
611
+ transition: all 0.2s ease !important;
612
  }
613
 
614
+ .gr-button-primary {
615
+ background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%) !important;
616
+ border: none !important;
617
+ color: white !important;
618
+ box-shadow: 0 2px 4px rgba(59, 130, 246, 0.3) !important;
619
+ }
620
+
621
+ .gr-button-primary:hover {
622
+ background: linear-gradient(135deg, #2563eb 0%, #1d4ed8 100%) !important;
623
+ transform: translateY(-1px) !important;
624
+ box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4) !important;
625
  }
626
 
627
+ /* Responsive design */
628
  @media (max-width: 768px) {
629
+ .header-title {
630
+ font-size: 28px;
 
 
 
 
631
  }
632
 
633
+ .model-stats {
634
+ grid-template-columns: repeat(2, 1fr);
 
635
  }
636
 
637
+ .social-links {
638
+ flex-wrap: wrap;
639
  }
640
 
641
+ .citation-boxes {
642
+ grid-template-columns: 1fr;
643
  }
644
  }
645
  """
646
 
647
+ # JavaScript for question button functionality
648
+ question_js = """
649
+ function setupQuestionButtons() {
650
+ document.addEventListener('click', function(e) {
651
+ if (e.target.classList.contains('question-button')) {
652
+ const question = e.target.textContent;
653
+ const textbox = document.querySelector('textarea[placeholder*="Ask about dental"]');
654
+ if (textbox) {
655
+ textbox.value = question;
656
+ textbox.dispatchEvent(new Event('input', { bubbles: true }));
657
+ }
658
+ }
659
+ });
660
+ }
661
+
662
+ document.addEventListener('DOMContentLoaded', setupQuestionButtons);
663
+ """
664
+
665
+ # Create the Gradio interface
666
+ with gr.Blocks(theme=gr.themes.Soft(), css=custom_css, js=question_js) as demo:
667
+
668
+ # Header with credits and social links
669
  gr.HTML(
670
  """
671
+ <div class="header-container">
672
  <h1 class="header-title">🦷 DentaInstruct-1.2B Demo</h1>
673
  <p class="header-subtitle">Advanced AI assistant for dental education and oral health information</p>
674
+ <div class="header-credits">
675
+ Model by <a href="https://huggingface.co/yasserrmd" target="_blank">yasserrmd</a> /
676
+ Space by <a href="https://huggingface.co/chrisvoncsefalvay" target="_blank">Chris von Csefalvay</a>
677
+ </div>
678
+ <div class="social-links">
679
+ <a href="https://github.com/chrisvoncsefalvay" target="_blank" class="social-link">GitHub</a>
680
+ <a href="https://twitter.com/epichrisis" target="_blank" class="social-link">X/Twitter</a>
681
+ <a href="https://chrisvoncsefalvay.com" target="_blank" class="social-link">Website</a>
682
+ </div>
683
  </div>
684
  """
685
  )
686
 
687
+ # Mini model card with skeuomorphic design
688
  gr.HTML(
689
  """
690
+ <div class="model-card">
691
+ <div class="model-card-title">
692
+ 🧠 Model Information
 
693
  </div>
694
+ <div class="model-stats">
695
+ <div class="model-stat">
696
+ <div class="stat-value">1.17B</div>
697
+ <div class="stat-label">Parameters</div>
698
+ </div>
699
+ <div class="model-stat">
700
+ <div class="stat-value">LFM2-1.2B</div>
701
+ <div class="stat-label">Base Model</div>
702
+ </div>
703
+ <div class="model-stat">
704
+ <div class="stat-value">MIRIAD</div>
705
+ <div class="stat-label">Dataset</div>
706
+ </div>
707
+ <div class="model-stat">
708
+ <div class="stat-value">2048</div>
709
+ <div class="stat-label">Context Length</div>
710
+ </div>
711
  </div>
712
+ <div class="model-description">
713
+ Specialised language model fine-tuned for dental education and oral health information.
714
+ Built on efficient LFM2 architecture with supervised fine-tuning on comprehensive dental content.
 
 
 
 
715
  </div>
716
  </div>
717
  """
718
  )
719
 
720
+ # Disclaimer box
721
  gr.HTML(
722
  """
723
  <div class="disclaimer-box">
 
733
  """
734
  )
735
 
736
+ # Main layout with chat on left, carousel on right
737
+ with gr.Row(elem_classes="main-layout"):
738
+ # Left side - Chat interface
739
+ with gr.Column(scale=2, elem_classes="chat-container"):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
740
  chatbot = gr.Chatbot(
741
  height=500,
742
  label="Dental Education Assistant",
 
758
  with gr.Row():
759
  submit = gr.Button("Send Question", variant="primary", scale=1)
760
  clear = gr.Button("Clear Chat", scale=1)
761
+
762
+ # Right side - Question carousel
763
+ with gr.Column(scale=1):
764
+ carousel_html = """
765
+ <div class="question-carousel">
766
+ <div class="carousel-title">💡 Quick Questions</div>
767
+ """
768
+
769
+ for category, questions in QUESTION_CATEGORIES.items():
770
+ carousel_html += f"""
771
+ <div class="carousel-card">
772
+ <div class="carousel-card-title">{category}</div>
773
+ """
774
+ for question in questions:
775
+ carousel_html += f"""
776
+ <button class="question-button" type="button">{question}</button>
777
+ """
778
+ carousel_html += "</div>"
779
+
780
+ carousel_html += "</div>"
781
+
782
+ gr.HTML(carousel_html)
783
 
784
+ # Advanced settings in collapsible section
785
+ with gr.Accordion("⚙️ Advanced Settings", open=False, elem_classes="advanced-settings"):
786
  with gr.Row():
787
  with gr.Column(scale=1):
788
  temperature = gr.Slider(
 
822
  info="Reduces repetitive phrases in responses"
823
  )
824
 
825
+ # Citation boxes section
826
+ gr.HTML(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
827
  """
828
+ <div class="citation-section">
829
+ <div class="citation-title">📚 Citations</div>
830
+ <div class="citation-boxes">
831
+ <div class="citation-box">
832
+ <h4>MIRIAD Dataset</h4>
833
+ <p>Training dataset used for fine-tuning the dental knowledge base.</p>
834
+ <div class="citation-content">@misc{miriad2024,
835
+ title={MIRIAD: A Multi-modal Instruction-following Dataset for Dentistry},
836
+ author={MIRIAD Team},
837
+ year={2024},
838
+ url={https://huggingface.co/datasets/miriad}
839
+ }</div>
840
+ </div>
841
+ <div class="citation-box">
842
+ <h4>DentaInstruct-1.2B Model</h4>
843
+ <p>The fine-tuned model used in this demonstration.</p>
844
+ <div class="citation-content">@misc{dentainstruct2024,
845
+ title={DentaInstruct-1.2B: A Dental Education Language Model},
846
+ author={yasserrmd},
847
+ year={2024},
848
+ url={https://huggingface.co/yasserrmd/DentaInstruct-1.2B}
849
+ }</div>
850
+ </div>
851
+ </div>
852
+ </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
853
  """
854
  )
855