shukdevdattaEX commited on
Commit
7bae2d0
·
verified ·
1 Parent(s): de0bbd0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +250 -63
app.py CHANGED
@@ -40,6 +40,12 @@ class ConversationMemory:
40
  }
41
  self.conversations.append(interaction)
42
 
 
 
 
 
 
 
43
  def get_relevant_context(self, query: str, limit: int = 3) -> List[Dict]:
44
  # Simple relevance scoring - in production, use embeddings
45
  relevant = []
@@ -79,9 +85,9 @@ class NexusAI:
79
  try:
80
  self.client = Together(api_key=api_key)
81
  self.api_key = api_key
82
- return True, "API key initialized successfully!"
83
  except Exception as e:
84
- return False, f"Failed to initialize API key: {str(e)}"
85
 
86
  def extract_text_from_pdf(self, pdf_path: str) -> str:
87
  """Extract text from PDF file"""
@@ -249,8 +255,8 @@ def process_pdf_input(pdf_file, user_question: str, api_key_status: str) -> str:
249
  if pdf_file is None:
250
  return "Please upload a PDF file first!"
251
 
252
- # Extract text from PDF
253
- extracted_text = nexus_ai.extract_text_from_pdf(pdf_file.name)
254
 
255
  if user_question.strip():
256
  return nexus_ai.generate_response(user_question, "pdf", extracted_text)
@@ -265,8 +271,8 @@ def process_image_input(image_file, user_question: str, api_key_status: str) ->
265
  if image_file is None:
266
  return "Please upload an image file first!"
267
 
268
- # Analyze image
269
- image_analysis = nexus_ai.analyze_image(image_file.name)
270
 
271
  if user_question.strip():
272
  return nexus_ai.generate_response(user_question, "image", image_analysis)
@@ -281,8 +287,8 @@ def process_audio_input(audio_file, user_question: str, api_key_status: str) ->
281
  if audio_file is None:
282
  return "Please upload an audio file first!"
283
 
284
- # Transcribe audio
285
- transcribed_text = nexus_ai.transcribe_audio(audio_file.name)
286
 
287
  if user_question.strip():
288
  combined_input = f"Transcribed audio: '{transcribed_text}'\n\nUser question: {user_question}"
@@ -318,7 +324,7 @@ def show_conversation_history() -> str:
318
  return "No conversation history yet. Start chatting to build your knowledge base!"
319
 
320
  history = "## 📚 Recent Conversation History\n\n"
321
- for i, conv in enumerate(nexus_ai.memory.conversations[-5:], 1): # Show last 5
322
  timestamp = datetime.fromisoformat(conv["timestamp"]).strftime("%H:%M:%S")
323
  history += f"**{i}. [{conv['input_type'].upper()}] {timestamp}**\n"
324
  history += f"Input: {conv['content'][:100]}{'...' if len(conv['content']) > 100 else ''}\n"
@@ -326,49 +332,168 @@ def show_conversation_history() -> str:
326
 
327
  return history
328
 
 
 
 
 
 
329
  # Create the Gradio interface
330
  def create_nexus_interface():
331
  with gr.Blocks(
332
  theme=gr.themes.Soft(),
333
  title="Nexus AI Assistant",
334
  css="""
 
335
  .gradio-container {
336
- max-width: 1200px !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
337
  }
338
- .api-key-box {
339
- border: 2px solid #e1e5e9;
340
- border-radius: 8px;
341
- padding: 15px;
342
- margin-bottom: 20px;
343
- background-color: #f8f9fa;
 
 
 
 
 
344
  }
345
  """
346
  ) as app:
347
 
348
  # Header
349
  gr.HTML("""
350
- <div style="text-align: center; padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 10px; margin-bottom: 20px;">
351
- <h1 style="color: white; margin: 0; font-size: 2.5em; font-weight: bold;">🚀 Nexus AI Assistant</h1>
352
- <p style="color: white; margin: 10px 0 0 0; font-size: 1.2em;">Creative Multimodal AI Powered by AFM-4.5B</p>
 
 
 
 
353
  </div>
354
  """)
355
 
356
  # API Key Section
357
- with gr.Group(elem_classes=["api-key-box"]):
358
- gr.HTML("<h3>🔑 API Configuration</h3>")
359
  with gr.Row():
360
  api_key_input = gr.Textbox(
361
  label="Together AI API Key",
362
  type="password",
363
  placeholder="Enter your Together AI API key here...",
364
- scale=3
 
 
 
 
 
 
 
365
  )
366
- api_key_btn = gr.Button("Initialize API Key", variant="primary", scale=1)
367
 
368
  api_key_status = gr.Textbox(
369
  label="Status",
370
  interactive=False,
371
- value="Please enter your API key to get started"
 
372
  )
373
 
374
  # Hidden state to track API key status
@@ -379,23 +504,32 @@ def create_nexus_interface():
379
 
380
  # Text Chat Tab
381
  with gr.Tab("💬 Text Chat"):
382
- with gr.Column():
383
- text_input = gr.Textbox(
384
- label="Your Message",
385
- placeholder="Ask me anything! I can help with creative tasks, analysis, problem-solving...",
386
- lines=3
387
- )
388
- text_btn = gr.Button("Send Message", variant="primary")
389
- text_output = gr.Textbox(
390
- label="Nexus AI Response",
391
- lines=8,
392
- interactive=False
393
- )
 
 
 
 
 
 
 
 
 
394
 
395
  # PDF Analysis Tab
396
  with gr.Tab("📄 PDF Analysis"):
397
  with gr.Row():
398
- with gr.Column(scale=1):
399
  pdf_file = gr.File(
400
  label="Upload PDF",
401
  file_types=[".pdf"]
@@ -403,21 +537,27 @@ def create_nexus_interface():
403
  pdf_question = gr.Textbox(
404
  label="Question about PDF (optional)",
405
  placeholder="What would you like to know about this document?",
406
- lines=2
 
 
 
 
 
 
407
  )
408
- pdf_btn = gr.Button("Analyze PDF", variant="primary")
409
 
410
- with gr.Column(scale=1):
411
  pdf_output = gr.Textbox(
412
  label="Analysis Result",
413
  lines=12,
414
- interactive=False
 
415
  )
416
 
417
  # Image Analysis Tab
418
  with gr.Tab("🖼️ Image Analysis"):
419
  with gr.Row():
420
- with gr.Column(scale=1):
421
  image_file = gr.Image(
422
  label="Upload Image",
423
  type="filepath"
@@ -425,21 +565,27 @@ def create_nexus_interface():
425
  image_question = gr.Textbox(
426
  label="Question about Image (optional)",
427
  placeholder="What would you like to know about this image?",
428
- lines=2
 
 
 
 
 
 
429
  )
430
- image_btn = gr.Button("Analyze Image", variant="primary")
431
 
432
- with gr.Column(scale=1):
433
  image_output = gr.Textbox(
434
  label="Analysis Result",
435
  lines=12,
436
- interactive=False
 
437
  )
438
 
439
  # Voice Processing Tab
440
  with gr.Tab("🎤 Voice Processing"):
441
  with gr.Row():
442
- with gr.Column(scale=1):
443
  audio_file = gr.Audio(
444
  label="Upload Audio",
445
  type="filepath"
@@ -447,21 +593,27 @@ def create_nexus_interface():
447
  audio_question = gr.Textbox(
448
  label="Additional Question (optional)",
449
  placeholder="Any specific question about the audio content?",
450
- lines=2
 
 
 
 
 
 
451
  )
452
- audio_btn = gr.Button("Process Audio", variant="primary")
453
 
454
- with gr.Column(scale=1):
455
  audio_output = gr.Textbox(
456
  label="Processing Result",
457
  lines=12,
458
- interactive=False
 
459
  )
460
 
461
  # Code Executor Tab
462
  with gr.Tab("⚡ Code Executor"):
463
  with gr.Row():
464
- with gr.Column(scale=1):
465
  code_input = gr.Code(
466
  label="Code Input",
467
  language="python",
@@ -480,31 +632,57 @@ def create_nexus_interface():
480
  label="Action",
481
  scale=1
482
  )
483
- code_btn = gr.Button("Process Code", variant="primary")
 
 
 
 
484
 
485
- with gr.Column(scale=1):
486
  code_output = gr.Textbox(
487
  label="Result & Analysis",
488
  lines=15,
489
- interactive=False
 
490
  )
491
 
492
  # Memory & History Tab
493
  with gr.Tab("🧠 Memory & History"):
494
- with gr.Column():
495
- gr.HTML("<h3>Conversation Memory</h3>")
496
  gr.HTML("<p>Nexus AI remembers your interactions and can connect insights across different input types.</p>")
497
 
498
- history_btn = gr.Button("Show Recent History", variant="secondary")
 
 
 
 
 
 
 
 
 
 
 
 
 
499
  history_output = gr.Textbox(
500
  label="Conversation History",
501
  lines=15,
502
- interactive=False
 
503
  )
504
 
505
  # Event handlers
 
 
 
 
 
 
 
506
  api_key_btn.click(
507
- fn=initialize_api_key,
508
  inputs=[api_key_input],
509
  outputs=[api_key_status, api_key_state]
510
  )
@@ -544,11 +722,20 @@ def create_nexus_interface():
544
  outputs=[history_output]
545
  )
546
 
 
 
 
 
 
547
  # Footer
548
  gr.HTML("""
549
- <div style="text-align: center; padding: 20px; margin-top: 30px; border-top: 1px solid #e1e5e9;">
550
- <p style="color: #666;">🚀 <strong>Nexus AI Assistant</strong> - Powered by AFM-4.5B | Built with ❤️ using Gradio</p>
551
- <p style="color: #888; font-size: 0.9em;">Multi-modal AI assistant for creative and analytical tasks</p>
 
 
 
 
552
  </div>
553
  """)
554
 
 
40
  }
41
  self.conversations.append(interaction)
42
 
43
+ def clear_history(self):
44
+ """Clear conversation history"""
45
+ self.conversations = []
46
+ self.context_graph = {}
47
+ self.session_data = {}
48
+
49
  def get_relevant_context(self, query: str, limit: int = 3) -> List[Dict]:
50
  # Simple relevance scoring - in production, use embeddings
51
  relevant = []
 
85
  try:
86
  self.client = Together(api_key=api_key)
87
  self.api_key = api_key
88
+ return True, "API key initialized successfully!"
89
  except Exception as e:
90
+ return False, f"Failed to initialize API key: {str(e)}"
91
 
92
  def extract_text_from_pdf(self, pdf_path: str) -> str:
93
  """Extract text from PDF file"""
 
255
  if pdf_file is None:
256
  return "Please upload a PDF file first!"
257
 
258
+ # Extract text from PDF - pdf_file is already a file path string
259
+ extracted_text = nexus_ai.extract_text_from_pdf(pdf_file)
260
 
261
  if user_question.strip():
262
  return nexus_ai.generate_response(user_question, "pdf", extracted_text)
 
271
  if image_file is None:
272
  return "Please upload an image file first!"
273
 
274
+ # Analyze image - image_file is already a file path string
275
+ image_analysis = nexus_ai.analyze_image(image_file)
276
 
277
  if user_question.strip():
278
  return nexus_ai.generate_response(user_question, "image", image_analysis)
 
287
  if audio_file is None:
288
  return "Please upload an audio file first!"
289
 
290
+ # Transcribe audio - audio_file is already a file path string
291
+ transcribed_text = nexus_ai.transcribe_audio(audio_file)
292
 
293
  if user_question.strip():
294
  combined_input = f"Transcribed audio: '{transcribed_text}'\n\nUser question: {user_question}"
 
324
  return "No conversation history yet. Start chatting to build your knowledge base!"
325
 
326
  history = "## 📚 Recent Conversation History\n\n"
327
+ for i, conv in enumerate(nexus_ai.memory.conversations[-10:], 1): # Show last 10
328
  timestamp = datetime.fromisoformat(conv["timestamp"]).strftime("%H:%M:%S")
329
  history += f"**{i}. [{conv['input_type'].upper()}] {timestamp}**\n"
330
  history += f"Input: {conv['content'][:100]}{'...' if len(conv['content']) > 100 else ''}\n"
 
332
 
333
  return history
334
 
335
+ def clear_conversation_history() -> str:
336
+ """Clear conversation history"""
337
+ nexus_ai.memory.clear_history()
338
+ return "✅ Conversation history has been cleared!"
339
+
340
  # Create the Gradio interface
341
  def create_nexus_interface():
342
  with gr.Blocks(
343
  theme=gr.themes.Soft(),
344
  title="Nexus AI Assistant",
345
  css="""
346
+ /* Center the main container */
347
  .gradio-container {
348
+ max-width: 1400px !important;
349
+ margin: 0 auto !important;
350
+ padding: 20px !important;
351
+ }
352
+
353
+ /* API Key section styling */
354
+ .api-key-section {
355
+ background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
356
+ border-radius: 12px;
357
+ padding: 20px;
358
+ margin-bottom: 25px;
359
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.07);
360
+ border: 1px solid #e1e8ed;
361
+ }
362
+
363
+ /* Button styling */
364
+ .primary-button {
365
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
366
+ border: none !important;
367
+ color: white !important;
368
+ font-weight: 600 !important;
369
+ border-radius: 8px !important;
370
+ padding: 12px 24px !important;
371
+ transition: all 0.3s ease !important;
372
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1) !important;
373
+ }
374
+
375
+ .primary-button:hover {
376
+ transform: translateY(-2px) !important;
377
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2) !important;
378
+ }
379
+
380
+ .secondary-button {
381
+ background: linear-gradient(135deg, #74b9ff 0%, #0984e3 100%) !important;
382
+ border: none !important;
383
+ color: white !important;
384
+ font-weight: 500 !important;
385
+ border-radius: 8px !important;
386
+ transition: all 0.3s ease !important;
387
+ }
388
+
389
+ .danger-button {
390
+ background: linear-gradient(135deg, #fd79a8 0%, #e84393 100%) !important;
391
+ border: none !important;
392
+ color: white !important;
393
+ font-weight: 500 !important;
394
+ border-radius: 8px !important;
395
+ transition: all 0.3s ease !important;
396
+ }
397
+
398
+ /* Tab styling */
399
+ .tab-nav button {
400
+ border-radius: 8px 8px 0 0 !important;
401
+ font-weight: 500 !important;
402
+ padding: 12px 20px !important;
403
+ }
404
+
405
+ /* Text area with scrollbar */
406
+ .scrollable-textarea textarea {
407
+ overflow-y: auto !important;
408
+ resize: vertical !important;
409
+ }
410
+
411
+ /* Card styling for better visual separation */
412
+ .input-card {
413
+ background: #ffffff;
414
+ border-radius: 10px;
415
+ padding: 20px;
416
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
417
+ border: 1px solid #f0f0f0;
418
+ margin-bottom: 15px;
419
+ }
420
+
421
+ .output-card {
422
+ background: #f8f9fc;
423
+ border-radius: 10px;
424
+ padding: 20px;
425
+ box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.02);
426
+ border: 1px solid #e9ecef;
427
+ }
428
+
429
+ /* Header gradient animation */
430
+ .header-gradient {
431
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #667eea 100%);
432
+ background-size: 200% 200%;
433
+ animation: gradientShift 4s ease infinite;
434
+ }
435
+
436
+ @keyframes gradientShift {
437
+ 0% { background-position: 0% 50%; }
438
+ 50% { background-position: 100% 50%; }
439
+ 100% { background-position: 0% 50%; }
440
+ }
441
+
442
+ /* Status indicator */
443
+ .status-success {
444
+ border-left: 4px solid #00b894 !important;
445
+ background-color: #d1f2eb !important;
446
  }
447
+
448
+ .status-error {
449
+ border-left: 4px solid #e17055 !important;
450
+ background-color: #fadbd8 !important;
451
+ }
452
+
453
+ /* Responsive design */
454
+ @media (max-width: 768px) {
455
+ .gradio-container {
456
+ padding: 10px !important;
457
+ }
458
  }
459
  """
460
  ) as app:
461
 
462
  # Header
463
  gr.HTML("""
464
+ <div class="header-gradient" style="text-align: center; padding: 30px; border-radius: 15px; margin-bottom: 25px;">
465
+ <h1 style="color: white; margin: 0; font-size: 3em; font-weight: 700; text-shadow: 2px 2px 4px rgba(0,0,0,0.3);">
466
+ 🚀 Nexus AI Assistant
467
+ </h1>
468
+ <p style="color: white; margin: 15px 0 0 0; font-size: 1.3em; text-shadow: 1px 1px 2px rgba(0,0,0,0.2);">
469
+ Creative Multimodal AI Powered by AFM-4.5B
470
+ </p>
471
  </div>
472
  """)
473
 
474
  # API Key Section
475
+ with gr.Group(elem_classes=["api-key-section"]):
476
+ gr.HTML("<h3 style='margin-top: 0; color: #2d3748;'>🔑 API Configuration</h3>")
477
  with gr.Row():
478
  api_key_input = gr.Textbox(
479
  label="Together AI API Key",
480
  type="password",
481
  placeholder="Enter your Together AI API key here...",
482
+ scale=3,
483
+ container=True
484
+ )
485
+ api_key_btn = gr.Button(
486
+ "Initialize API Key",
487
+ variant="primary",
488
+ scale=1,
489
+ elem_classes=["primary-button"]
490
  )
 
491
 
492
  api_key_status = gr.Textbox(
493
  label="Status",
494
  interactive=False,
495
+ value="Please enter your API key to get started",
496
+ elem_classes=["scrollable-textarea"]
497
  )
498
 
499
  # Hidden state to track API key status
 
504
 
505
  # Text Chat Tab
506
  with gr.Tab("💬 Text Chat"):
507
+ with gr.Row():
508
+ with gr.Column(scale=1, elem_classes=["input-card"]):
509
+ text_input = gr.Textbox(
510
+ label="Your Message",
511
+ placeholder="Ask me anything! I can help with creative tasks, analysis, problem-solving...",
512
+ lines=4,
513
+ elem_classes=["scrollable-textarea"]
514
+ )
515
+ text_btn = gr.Button(
516
+ "Send Message",
517
+ variant="primary",
518
+ elem_classes=["primary-button"]
519
+ )
520
+
521
+ with gr.Column(scale=1, elem_classes=["output-card"]):
522
+ text_output = gr.Textbox(
523
+ label="Nexus AI Response",
524
+ lines=10,
525
+ interactive=False,
526
+ elem_classes=["scrollable-textarea"]
527
+ )
528
 
529
  # PDF Analysis Tab
530
  with gr.Tab("📄 PDF Analysis"):
531
  with gr.Row():
532
+ with gr.Column(scale=1, elem_classes=["input-card"]):
533
  pdf_file = gr.File(
534
  label="Upload PDF",
535
  file_types=[".pdf"]
 
537
  pdf_question = gr.Textbox(
538
  label="Question about PDF (optional)",
539
  placeholder="What would you like to know about this document?",
540
+ lines=3,
541
+ elem_classes=["scrollable-textarea"]
542
+ )
543
+ pdf_btn = gr.Button(
544
+ "Analyze PDF",
545
+ variant="primary",
546
+ elem_classes=["primary-button"]
547
  )
 
548
 
549
+ with gr.Column(scale=1, elem_classes=["output-card"]):
550
  pdf_output = gr.Textbox(
551
  label="Analysis Result",
552
  lines=12,
553
+ interactive=False,
554
+ elem_classes=["scrollable-textarea"]
555
  )
556
 
557
  # Image Analysis Tab
558
  with gr.Tab("🖼️ Image Analysis"):
559
  with gr.Row():
560
+ with gr.Column(scale=1, elem_classes=["input-card"]):
561
  image_file = gr.Image(
562
  label="Upload Image",
563
  type="filepath"
 
565
  image_question = gr.Textbox(
566
  label="Question about Image (optional)",
567
  placeholder="What would you like to know about this image?",
568
+ lines=3,
569
+ elem_classes=["scrollable-textarea"]
570
+ )
571
+ image_btn = gr.Button(
572
+ "Analyze Image",
573
+ variant="primary",
574
+ elem_classes=["primary-button"]
575
  )
 
576
 
577
+ with gr.Column(scale=1, elem_classes=["output-card"]):
578
  image_output = gr.Textbox(
579
  label="Analysis Result",
580
  lines=12,
581
+ interactive=False,
582
+ elem_classes=["scrollable-textarea"]
583
  )
584
 
585
  # Voice Processing Tab
586
  with gr.Tab("🎤 Voice Processing"):
587
  with gr.Row():
588
+ with gr.Column(scale=1, elem_classes=["input-card"]):
589
  audio_file = gr.Audio(
590
  label="Upload Audio",
591
  type="filepath"
 
593
  audio_question = gr.Textbox(
594
  label="Additional Question (optional)",
595
  placeholder="Any specific question about the audio content?",
596
+ lines=3,
597
+ elem_classes=["scrollable-textarea"]
598
+ )
599
+ audio_btn = gr.Button(
600
+ "Process Audio",
601
+ variant="primary",
602
+ elem_classes=["primary-button"]
603
  )
 
604
 
605
+ with gr.Column(scale=1, elem_classes=["output-card"]):
606
  audio_output = gr.Textbox(
607
  label="Processing Result",
608
  lines=12,
609
+ interactive=False,
610
+ elem_classes=["scrollable-textarea"]
611
  )
612
 
613
  # Code Executor Tab
614
  with gr.Tab("⚡ Code Executor"):
615
  with gr.Row():
616
+ with gr.Column(scale=1, elem_classes=["input-card"]):
617
  code_input = gr.Code(
618
  label="Code Input",
619
  language="python",
 
632
  label="Action",
633
  scale=1
634
  )
635
+ code_btn = gr.Button(
636
+ "Process Code",
637
+ variant="primary",
638
+ elem_classes=["primary-button"]
639
+ )
640
 
641
+ with gr.Column(scale=1, elem_classes=["output-card"]):
642
  code_output = gr.Textbox(
643
  label="Result & Analysis",
644
  lines=15,
645
+ interactive=False,
646
+ elem_classes=["scrollable-textarea"]
647
  )
648
 
649
  # Memory & History Tab
650
  with gr.Tab("🧠 Memory & History"):
651
+ with gr.Column(elem_classes=["input-card"]):
652
+ gr.HTML("<h3 style='margin-top: 0;'>Conversation Memory</h3>")
653
  gr.HTML("<p>Nexus AI remembers your interactions and can connect insights across different input types.</p>")
654
 
655
+ with gr.Row():
656
+ history_btn = gr.Button(
657
+ "Show Recent History",
658
+ variant="secondary",
659
+ elem_classes=["secondary-button"],
660
+ scale=1
661
+ )
662
+ clear_btn = gr.Button(
663
+ "Clear History",
664
+ variant="secondary",
665
+ elem_classes=["danger-button"],
666
+ scale=1
667
+ )
668
+
669
  history_output = gr.Textbox(
670
  label="Conversation History",
671
  lines=15,
672
+ interactive=False,
673
+ elem_classes=["scrollable-textarea"]
674
  )
675
 
676
  # Event handlers
677
+ def update_api_status(api_key):
678
+ message, status = initialize_api_key(api_key)
679
+ if status == "success":
680
+ return gr.update(value=message, elem_classes=["scrollable-textarea", "status-success"]), status
681
+ else:
682
+ return gr.update(value=message, elem_classes=["scrollable-textarea", "status-error"]), status
683
+
684
  api_key_btn.click(
685
+ fn=update_api_status,
686
  inputs=[api_key_input],
687
  outputs=[api_key_status, api_key_state]
688
  )
 
722
  outputs=[history_output]
723
  )
724
 
725
+ clear_btn.click(
726
+ fn=clear_conversation_history,
727
+ outputs=[history_output]
728
+ )
729
+
730
  # Footer
731
  gr.HTML("""
732
+ <div style="text-align: center; padding: 25px; margin-top: 30px; border-top: 2px solid #e9ecef; background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%); border-radius: 10px;">
733
+ <p style="color: #495057; font-size: 1.1em; margin: 0;">
734
+ 🚀 <strong>Nexus AI Assistant</strong> - Powered by AFM-4.5B | Built with ❤️ using Gradio
735
+ </p>
736
+ <p style="color: #6c757d; font-size: 0.9em; margin: 5px 0 0 0;">
737
+ Multi-modal AI assistant for creative and analytical tasks
738
+ </p>
739
  </div>
740
  """)
741