ElMETRICO commited on
Commit
4b5d27d
·
verified ·
1 Parent(s): a158874

Update CrossTalk AI with clean standard UI

Browse files
Files changed (1) hide show
  1. app.py +214 -107
app.py CHANGED
@@ -258,140 +258,203 @@ def safe_search(query):
258
  )
259
 
260
 
 
261
  custom_css = """
262
  .gradio-container {
263
- background:
264
- radial-gradient(circle at 15% 5%, rgba(139,92,246,0.32), transparent 28%),
265
- radial-gradient(circle at 90% 10%, rgba(168,85,247,0.22), transparent 26%),
266
- linear-gradient(180deg, #07020F 0%, #090716 50%, #07020F 100%) !important;
267
- color: #F8F5FF !important;
268
- font-family: Inter, ui-sans-serif, system-ui, sans-serif !important;
269
  }
270
 
271
  #shell {
272
- max-width: 1280px;
273
- margin: auto;
 
274
  }
275
 
276
  .hero {
277
- background: linear-gradient(135deg, rgba(18,16,38,0.96), rgba(37,22,78,0.82));
278
- border: 1px solid rgba(255,255,255,0.10);
279
- border-radius: 30px;
280
- padding: 34px;
281
  margin-bottom: 22px;
282
- box-shadow: 0 26px 80px rgba(0,0,0,0.42);
283
  }
284
 
285
  .badge {
286
  display: inline-block;
287
- padding: 8px 13px;
288
  border-radius: 999px;
289
- background: rgba(139,92,246,0.16);
290
- border: 1px solid rgba(139,92,246,0.36);
291
- color: #EDE7FF;
292
- font-weight: 800;
293
- font-size: 13px;
294
  margin-bottom: 14px;
295
  }
296
 
297
  .title {
298
- font-size: 48px;
299
- line-height: 1.02;
300
- font-weight: 950;
301
- letter-spacing: -0.05em;
302
- margin: 0;
303
- background: linear-gradient(135deg, #FFFFFF, #D9CCFF, #A78BFA);
304
- -webkit-background-clip: text;
305
- -webkit-text-fill-color: transparent;
306
  }
307
 
308
  .subtitle {
 
 
 
309
  max-width: 980px;
310
- margin-top: 15px;
311
- color: #BDB2DE;
312
- font-size: 16px;
313
- line-height: 1.7;
314
  }
315
 
316
- .metrics {
317
- display: grid;
318
- grid-template-columns: repeat(4, 1fr);
319
- gap: 14px;
320
- margin-top: 24px;
321
  }
322
 
323
- .metric {
324
- padding: 17px;
325
- border-radius: 20px;
326
- background: rgba(255,255,255,0.055);
327
- border: 1px solid rgba(255,255,255,0.09);
 
 
 
328
  }
329
 
330
- .metric strong {
331
- display: block;
332
- color: #FFFFFF;
333
- font-size: 25px;
334
- font-weight: 950;
 
335
  }
336
 
337
- .metric span {
338
- color: #B8ADD8;
339
- font-size: 12px;
340
  }
341
 
342
- .panel {
343
- background: rgba(18,16,38,0.78) !important;
344
- border: 1px solid rgba(255,255,255,0.10) !important;
345
- border-radius: 24px !important;
346
- padding: 18px !important;
347
- box-shadow: 0 20px 55px rgba(0,0,0,0.30);
348
  }
349
 
350
- button.primary-btn {
351
- background: linear-gradient(135deg, #8B5CF6, #A855F7) !important;
352
- border: none !important;
353
- border-radius: 16px !important;
354
- color: white !important;
355
- font-weight: 900 !important;
356
- min-height: 48px !important;
357
  }
358
 
359
- button.secondary-btn {
360
- background: rgba(255,255,255,0.08) !important;
361
- border: 1px solid rgba(255,255,255,0.12) !important;
362
- border-radius: 16px !important;
363
- color: white !important;
364
- font-weight: 800 !important;
365
- min-height: 48px !important;
366
  }
367
 
368
  textarea, input {
369
- background: rgba(5,4,14,0.78) !important;
370
- color: white !important;
371
- border: 1px solid rgba(255,255,255,0.14) !important;
372
- border-radius: 16px !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
373
  }
374
 
375
  .footer {
376
  text-align: center;
377
- color: #A99FD0;
378
  font-size: 13px;
379
  line-height: 1.6;
380
  margin-top: 18px;
381
  }
382
 
 
 
 
 
383
  @media (max-width: 900px) {
384
- .title { font-size: 34px; }
385
- .metrics { grid-template-columns: repeat(2, 1fr); }
 
386
  }
387
  """
388
 
389
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
390
  with gr.Blocks(
391
  css=custom_css,
392
- theme=gr.themes.Soft(
393
- primary_hue="violet",
394
- secondary_hue="purple",
395
  neutral_hue="slate"
396
  )
397
  ) as demo:
@@ -400,35 +463,43 @@ with gr.Blocks(
400
  gr.HTML(
401
  """
402
  <div class="hero">
403
- <div class="badge">🌐 Full trained hybrid retrieval system</div>
404
  <h1 class="title">CrossTalk AI</h1>
405
  <div class="subtitle">
406
- A confidence-aware lexical retrieval and translation support system for low-resource ethnic languages of Bangladesh.
407
- It combines exact dictionary matching, base-form matching, fine-tuned multilingual E5 semantic fallback,
408
- FAISS vector search, and safe output handling.
409
  </div>
410
- <div class="metrics">
411
- <div class="metric"><strong>12</strong><span>Ethnic language groups</span></div>
412
- <div class="metric"><strong>70K+</strong><span>Indexed source entries</span></div>
413
- <div class="metric"><strong>E5</strong><span>Fine-tuned semantic retriever</span></div>
414
- <div class="metric"><strong>FAISS</strong><span>Vector search backend</span></div>
 
415
  </div>
416
  </div>
417
  """
418
  )
419
 
420
- with gr.Row():
421
- with gr.Column(scale=5, elem_classes=["panel"]):
422
- gr.Markdown("### Search source word")
 
 
 
 
 
 
 
 
423
  query = gr.Textbox(
424
- label="Input word",
425
- placeholder="Try: kəkhyáŋ, Hula, Aina, aam, bajaoo",
426
  lines=1
427
  )
428
 
429
  with gr.Row():
430
- clear_btn = gr.Button("Clear", elem_classes=["secondary-btn"])
431
- submit_btn = gr.Button("Search", elem_classes=["primary-btn"])
432
 
433
  gr.Examples(
434
  examples=[
@@ -440,34 +511,70 @@ with gr.Blocks(
440
  ["unknown tribal word"]
441
  ],
442
  inputs=query,
443
- label="Quick examples"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
444
  )
445
 
446
- with gr.Column(scale=7, elem_classes=["panel"]):
447
- gr.Markdown("### Retrieval output")
448
- status = gr.Textbox(label="System status", lines=1)
449
  summary = gr.Markdown(
450
- value="Enter a source word to retrieve verified dictionary matches or semantic candidates."
 
 
 
 
451
  )
 
452
  results = gr.Dataframe(
453
- label="Results",
 
454
  interactive=False,
455
- wrap=True
 
456
  )
457
 
458
  gr.HTML(
459
  """
460
  <div class="footer">
461
- Exact and base-form matches are verified dictionary outputs.
462
- Fine-tuned semantic fallback results are candidate suggestions only and should not be treated as confirmed translations.
463
  </div>
464
  """
465
  )
466
 
467
- submit_btn.click(fn=safe_search, inputs=query, outputs=[status, summary, results])
468
- query.submit(fn=safe_search, inputs=query, outputs=[status, summary, results])
 
 
 
 
 
 
 
 
 
 
469
  clear_btn.click(
470
- fn=lambda: ("", "Ready.", "Enter a source word to retrieve verified dictionary matches or semantic candidates.", pd.DataFrame()),
 
 
 
 
 
471
  inputs=None,
472
  outputs=[query, status, summary, results]
473
  )
 
258
  )
259
 
260
 
261
+
262
  custom_css = """
263
  .gradio-container {
264
+ background: #0B0F19 !important;
265
+ color: #F8FAFC !important;
266
+ font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif !important;
 
 
 
267
  }
268
 
269
  #shell {
270
+ max-width: 1180px;
271
+ margin: 0 auto;
272
+ padding: 26px 18px 36px 18px;
273
  }
274
 
275
  .hero {
276
+ background: #111827;
277
+ border: 1px solid #243044;
278
+ border-radius: 18px;
279
+ padding: 26px 30px;
280
  margin-bottom: 22px;
281
+ box-shadow: 0 18px 45px rgba(0,0,0,0.24);
282
  }
283
 
284
  .badge {
285
  display: inline-block;
286
+ padding: 6px 11px;
287
  border-radius: 999px;
288
+ background: #172033;
289
+ border: 1px solid #2B3A55;
290
+ color: #CBD5E1;
291
+ font-weight: 700;
292
+ font-size: 12px;
293
  margin-bottom: 14px;
294
  }
295
 
296
  .title {
297
+ font-size: 34px;
298
+ line-height: 1.12;
299
+ font-weight: 850;
300
+ letter-spacing: -0.035em;
301
+ margin: 0 0 10px 0;
302
+ color: #FFFFFF;
 
 
303
  }
304
 
305
  .subtitle {
306
+ color: #CBD5E1;
307
+ font-size: 15px;
308
+ line-height: 1.65;
309
  max-width: 980px;
 
 
 
 
310
  }
311
 
312
+ .info-strip {
313
+ display: flex;
314
+ flex-wrap: wrap;
315
+ gap: 10px;
316
+ margin-top: 18px;
317
  }
318
 
319
+ .info-pill {
320
+ padding: 9px 12px;
321
+ border-radius: 10px;
322
+ background: #0F172A;
323
+ border: 1px solid #26344D;
324
+ color: #E2E8F0;
325
+ font-size: 13px;
326
+ font-weight: 650;
327
  }
328
 
329
+ .main-card {
330
+ background: #111827 !important;
331
+ border: 1px solid #243044 !important;
332
+ border-radius: 18px !important;
333
+ padding: 22px !important;
334
+ box-shadow: 0 16px 38px rgba(0,0,0,0.22);
335
  }
336
 
337
+ .search-card {
338
+ border-top: 4px solid #3B82F6 !important;
 
339
  }
340
 
341
+ .output-card {
342
+ border-top: 4px solid #22C55E !important;
 
 
 
 
343
  }
344
 
345
+ .section-title {
346
+ color: #F8FAFC;
347
+ font-size: 19px;
348
+ font-weight: 800;
349
+ margin-bottom: 4px;
 
 
350
  }
351
 
352
+ .section-subtitle {
353
+ color: #94A3B8;
354
+ font-size: 13px;
355
+ line-height: 1.5;
356
+ margin-bottom: 16px;
 
 
357
  }
358
 
359
  textarea, input {
360
+ background: #0B1220 !important;
361
+ color: #FFFFFF !important;
362
+ border: 1px solid #334155 !important;
363
+ border-radius: 12px !important;
364
+ font-size: 15px !important;
365
+ }
366
+
367
+ textarea:focus, input:focus {
368
+ border-color: #60A5FA !important;
369
+ box-shadow: 0 0 0 3px rgba(59,130,246,0.18) !important;
370
+ }
371
+
372
+ button.search-button {
373
+ background: #2563EB !important;
374
+ border: 1px solid #2563EB !important;
375
+ border-radius: 12px !important;
376
+ color: #FFFFFF !important;
377
+ font-weight: 800 !important;
378
+ min-height: 46px !important;
379
+ }
380
+
381
+ button.search-button:hover {
382
+ background: #1D4ED8 !important;
383
+ }
384
+
385
+ button.clear-button {
386
+ background: #1F2937 !important;
387
+ border: 1px solid #374151 !important;
388
+ border-radius: 12px !important;
389
+ color: #E5E7EB !important;
390
+ font-weight: 750 !important;
391
+ min-height: 46px !important;
392
+ }
393
+
394
+ .status-panel textarea {
395
+ background: #07111F !important;
396
+ border: 1px solid #334155 !important;
397
+ color: #FFFFFF !important;
398
+ font-weight: 750 !important;
399
+ }
400
+
401
+ .result-note {
402
+ background: #0F172A;
403
+ border: 1px solid #243044;
404
+ border-radius: 12px;
405
+ padding: 12px 14px;
406
+ color: #CBD5E1;
407
+ font-size: 13px;
408
+ line-height: 1.55;
409
+ }
410
+
411
+ .dataframe {
412
+ border-radius: 12px !important;
413
+ overflow: hidden !important;
414
+ border: 1px solid #243044 !important;
415
  }
416
 
417
  .footer {
418
  text-align: center;
419
+ color: #94A3B8;
420
  font-size: 13px;
421
  line-height: 1.6;
422
  margin-top: 18px;
423
  }
424
 
425
+ #examples-block {
426
+ margin-top: 12px;
427
+ }
428
+
429
  @media (max-width: 900px) {
430
+ .title {
431
+ font-size: 28px;
432
+ }
433
  }
434
  """
435
 
436
 
437
+ EMPTY_RESULTS = pd.DataFrame(
438
+ columns=[
439
+ "query",
440
+ "score",
441
+ "method",
442
+ "confidence",
443
+ "language",
444
+ "source_text",
445
+ "english_meaning",
446
+ "bangla_meaning",
447
+ "part_of_speech",
448
+ "note"
449
+ ]
450
+ )
451
+
452
+
453
  with gr.Blocks(
454
  css=custom_css,
455
+ theme=gr.themes.Base(
456
+ primary_hue="blue",
457
+ secondary_hue="slate",
458
  neutral_hue="slate"
459
  )
460
  ) as demo:
 
463
  gr.HTML(
464
  """
465
  <div class="hero">
466
+ <div class="badge">Full trained hybrid retrieval system</div>
467
  <h1 class="title">CrossTalk AI</h1>
468
  <div class="subtitle">
469
+ A retrieval-based language identification and translation support system for low-resource ethnic languages of Bangladesh.
470
+ It combines verified dictionary lookup with fine-tuned E5 semantic retrieval and FAISS vector search.
 
471
  </div>
472
+ <div class="info-strip">
473
+ <div class="info-pill">12 language groups</div>
474
+ <div class="info-pill">70K+ indexed entries</div>
475
+ <div class="info-pill">Fine-tuned E5 retriever</div>
476
+ <div class="info-pill">FAISS vector search</div>
477
+ <div class="info-pill">Confidence-aware output</div>
478
  </div>
479
  </div>
480
  """
481
  )
482
 
483
+ with gr.Row(equal_height=False):
484
+ with gr.Column(scale=5, elem_classes=["main-card", "search-card"]):
485
+ gr.HTML(
486
+ """
487
+ <div class="section-title">Search input</div>
488
+ <div class="section-subtitle">
489
+ Enter an ethnic source word. Exact and base-form matches are treated as verified dictionary outputs.
490
+ </div>
491
+ """
492
+ )
493
+
494
  query = gr.Textbox(
495
+ label="Source word",
496
+ placeholder="Example: kəkhyáŋ, Hula, Aina, aam, bajaoo",
497
  lines=1
498
  )
499
 
500
  with gr.Row():
501
+ clear_btn = gr.Button("Clear", elem_classes=["clear-button"])
502
+ submit_btn = gr.Button("Search", elem_classes=["search-button"])
503
 
504
  gr.Examples(
505
  examples=[
 
511
  ["unknown tribal word"]
512
  ],
513
  inputs=query,
514
+ label="Examples",
515
+ elem_id="examples-block"
516
+ )
517
+
518
+ with gr.Column(scale=7, elem_classes=["main-card", "output-card"]):
519
+ gr.HTML(
520
+ """
521
+ <div class="section-title">Retrieval output</div>
522
+ <div class="section-subtitle">
523
+ The system returns verified dictionary matches first. Semantic fallback appears only when no verified match is found.
524
+ </div>
525
+ """
526
+ )
527
+
528
+ status = gr.Textbox(
529
+ label="System status",
530
+ lines=1,
531
+ elem_classes=["status-panel"],
532
+ value="Ready."
533
  )
534
 
 
 
 
535
  summary = gr.Markdown(
536
+ value="""
537
+ <div class="result-note">
538
+ Enter a source word and click Search. Results will appear below.
539
+ </div>
540
+ """
541
  )
542
+
543
  results = gr.Dataframe(
544
+ label="Results table",
545
+ value=EMPTY_RESULTS,
546
  interactive=False,
547
+ wrap=True,
548
+ max_height=420
549
  )
550
 
551
  gr.HTML(
552
  """
553
  <div class="footer">
554
+ Exact/base-form matches are verified dictionary outputs. Fine-tuned semantic fallback results are candidate suggestions only, not confirmed translations.
 
555
  </div>
556
  """
557
  )
558
 
559
+ submit_btn.click(
560
+ fn=safe_search,
561
+ inputs=query,
562
+ outputs=[status, summary, results]
563
+ )
564
+
565
+ query.submit(
566
+ fn=safe_search,
567
+ inputs=query,
568
+ outputs=[status, summary, results]
569
+ )
570
+
571
  clear_btn.click(
572
+ fn=lambda: (
573
+ "",
574
+ "Ready.",
575
+ '<div class="result-note">Enter a source word and click Search. Results will appear below.</div>',
576
+ EMPTY_RESULTS
577
+ ),
578
  inputs=None,
579
  outputs=[query, status, summary, results]
580
  )