aldohenrique commited on
Commit
890a80e
·
verified ·
1 Parent(s): c7487ca

Update interface.py

Browse files
Files changed (1) hide show
  1. interface.py +298 -837
interface.py CHANGED
@@ -8,604 +8,189 @@ from ai_logic import (
8
  inicializar_sistema
9
  )
10
 
11
- # CSS Moderno - Otimizado para usar toda a tela
12
  css_customizado = """
13
- /* === VARIÁVEIS CSS === */
14
- :root {
15
- --bg-primary: #212121 !important;
16
- --bg-secondary: #2f2f2f !important;
17
- --bg-tertiary: #3c4043 !important;
18
- --bg-chat: #f8f9fa !important;
19
- --bg-user: #e3f2fd !important;
20
- --bg-assistant: #ffffff !important;
21
- --border-color: #e0e0e0 !important;
22
- --border-dark: #565869 !important;
23
- --text-primary: #1a1a1a !important;
24
- --text-secondary: #555555 !important;
25
- --text-on-dark: #ffffff !important;
26
- --text-chat: #2d2d2d !important;
27
- --accent: #1976d2 !important;
28
- --accent-hover: #1565c0 !important;
29
- --shadow: 0 2px 16px rgba(0, 0, 0, 0.1) !important;
30
- --shadow-lg: 0 8px 28px rgba(0, 0, 0, 0.12) !important;
31
- --radius: 12px !important;
32
- --radius-lg: 16px !important;
33
- --sidebar-width: 280px !important;
34
- --header-height: 60px !important;
35
- --input-height: 80px !important;
36
- }
37
-
38
-
39
- /* === RESET E BASE === */
40
- * {
41
- box-sizing: border-box;
42
- margin: 0;
43
- padding: 0;
44
- color-scheme: light !important; /* Força tema claro */
45
- }
46
-
47
- html, body {
48
  height: 100vh !important;
49
- max-height: 100vh !important;
50
- overflow: hidden !important;
51
- background: var(--bg-chat) !important;
52
- color: var(--text-primary) !important;
53
- }
54
-
55
- body, .gradio-container {
56
- font-family: 'Söhne', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
57
- background: var(--bg-chat) !important;
58
- color: var(--text-primary) !important;
59
- height: 100vh !important;
60
- max-height: 100vh !important;
61
- width: 100vw !important;
62
- max-width: 100vw !important;
63
- overflow: hidden !important;
64
- line-height: 1.6;
65
- padding: 0 !important;
66
- margin: 0 !important;
67
- }
68
-
69
- .gradio-container > div {
70
- height: 100vh !important;
71
- max-height: 100vh !important;
72
- width: 100vw !important;
73
- max-width: 100vw !important;
74
- padding: 0 !important;
75
- margin: 0 !important;
76
- overflow: hidden !important;
77
- }
78
-
79
- /* === LAYOUT PRINCIPAL === */
80
- .main-container {
81
- display: flex !important;
82
- height: 100vh !important;
83
- max-height: 100vh !important;
84
- width: 100vw !important;
85
- max-width: 100vw !important;
86
- position: fixed !important;
87
- top: 0 !important;
88
- left: 0 !important;
89
- overflow: hidden !important;
90
- padding: 0 !important;
91
- margin: 0 !important;
92
- }
93
-
94
- /* === SIDEBAR === */
95
- .sidebar {
96
- width: var(--sidebar-width) !important;
97
- min-width: var(--sidebar-width) !important;
98
- max-width: var(--sidebar-width) !important;
99
- background: var(--bg-primary);
100
- border-right: 1px solid var(--border-dark);
101
- padding: 20px;
102
  display: flex;
103
  flex-direction: column;
104
- gap: 20px;
105
- height: 100vh !important;
106
- max-height: 100vh !important;
107
- overflow-y: auto;
108
- transition: transform 0.3s ease;
109
- z-index: 1000;
110
- position: relative;
111
- }
112
-
113
- .sidebar-header {
114
- text-align: center;
115
- margin-bottom: 20px;
116
- padding: 16px 0;
117
- flex-shrink: 0;
118
- }
119
-
120
- .sidebar-title {
121
- font-size: 20px;
122
- font-weight: 700;
123
- color: var(--text-on-dark);
124
- margin-bottom: 4px;
125
- }
126
-
127
- .sidebar-subtitle {
128
- font-size: 13px;
129
- color: #8e8ea0;
130
- opacity: 0.8;
131
  }
132
-
133
- .sidebar-section {
134
- margin-bottom: 24px;
 
 
135
  flex-shrink: 0;
136
  }
137
-
138
- .sidebar-section-title {
139
- color: #8e8ea0;
140
- font-size: 11px;
141
- font-weight: 600;
142
- text-transform: uppercase;
143
- margin-bottom: 12px;
144
- letter-spacing: 1px;
145
- }
146
-
147
- .new-chat-btn {
148
- width: 100% !important;
149
- background: linear-gradient(135deg, var(--accent), #0ea5e9) !important;
150
  color: white !important;
151
- border: none !important;
152
- border-radius: var(--radius) !important;
153
- padding: 14px 16px !important;
154
- font-weight: 600 !important;
155
- font-size: 14px !important;
156
- transition: all 0.2s ease !important;
157
- box-shadow: var(--shadow) !important;
158
- cursor: pointer !important;
159
- }
160
-
161
- .new-chat-btn:hover {
162
- background: linear-gradient(135deg, var(--accent-hover), #0284c7) !important;
163
- transform: translateY(-1px) !important;
164
- box-shadow: var(--shadow-lg) !important;
165
- }
166
-
167
- /* Dropdown customizado */
168
- .sidebar .gr-dropdown {
169
- background: var(--bg-secondary) !important;
170
- border: 1px solid var(--border-dark) !important;
171
- border-radius: var(--radius) !important;
172
- color: var(--text-on-dark) !important;
173
- }
174
-
175
- .sidebar .gr-dropdown > div {
176
- background: var(--bg-secondary) !important;
177
- border: none !important;
178
- color: var(--text-on-dark) !important;
179
- }
180
-
181
- /* === ÁREA DO CHAT === */
182
- .chat-main {
183
- flex: 1 !important;
184
- display: flex !important;
185
- flex-direction: column !important;
186
- height: 100vh !important;
187
- max-height: 100vh !important;
188
- width: calc(100vw - var(--sidebar-width)) !important;
189
- background: var(--bg-chat);
190
- position: relative;
191
- overflow: hidden !important;
192
- }
193
-
194
- /* Header do Chat */
195
- .chat-header {
196
- background: var(--bg-chat);
197
- border-bottom: 1px solid var(--border-color);
198
- padding: 12px 20px;
199
- display: flex;
200
- align-items: center;
201
- justify-content: space-between;
202
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
203
- z-index: 100;
204
  flex-shrink: 0;
205
- height: var(--header-height);
206
- min-height: var(--header-height);
207
- max-height: var(--header-height);
208
  }
209
-
210
- .chat-header-title {
211
- font-size: 18px;
212
- font-weight: 600;
213
- color: var(--text-chat);
214
  }
215
-
216
- .mobile-menu-btn {
217
- display: none;
218
- background: none !important;
219
- border: none !important;
220
- font-size: 20px !important;
221
- color: var(--text-chat) !important;
222
- cursor: pointer !important;
223
- padding: 8px !important;
224
- border-radius: 8px !important;
225
  }
226
-
227
- .mobile-menu-btn:hover {
228
- background: var(--bg-user) !important;
 
 
 
229
  }
230
-
231
- /* Container de Mensagens */
232
- .messages-container {
233
- flex: 1 !important;
234
- height: calc(100vh - var(--header-height) - var(--input-height)) !important;
235
- max-height: calc(100vh - var(--header-height) - var(--input-height)) !important;
236
- overflow-y: auto !important;
237
- overflow-x: hidden !important;
238
- padding: 0 !important;
239
- margin: 0 !important;
240
- background: var(--bg-chat);
241
- position: relative;
242
- width: 100% !important;
243
  }
244
-
245
- /* Estilização do Chat */
246
- #chat {
247
  height: 100% !important;
248
- max-height: 100% !important;
249
- min-height: 100% !important;
250
- width: 100% !important;
251
- padding: 0 !important;
252
- margin: 0 !important;
253
- background: var(--bg-chat) !important;
254
- color: var(--text-chat) !important;
255
- overflow-y: auto !important;
256
- overflow-x: hidden !important;
257
- }
258
-
259
- #chat * {
260
- color: var(--text-chat) !important;
261
  }
262
-
263
- #chat .message {
264
- margin: 0 !important;
265
- padding: 20px !important;
266
- border: none !important;
267
- border-radius: 0 !important;
268
- max-width: 100% !important;
269
- width: 100% !important;
270
- word-wrap: break-word !important;
271
- overflow-wrap: break-word !important;
272
- color: var(--text-chat) !important;
273
- }
274
-
275
- #chat .message.user {
276
- background: var(--bg-user) !important;
277
- border-bottom: 1px solid #bbdefb !important;
278
- color: var(--text-chat) !important;
279
- }
280
-
281
- #chat .message.user * {
282
- color: var(--text-chat) !important;
283
- }
284
-
285
- #chat .message.bot {
286
- background: var(--bg-assistant) !important;
287
- border-bottom: 1px solid var(--border-color) !important;
288
- color: var(--text-chat) !important;
289
- }
290
-
291
- #chat .message.bot * {
292
- color: var(--text-chat) !important;
293
- }
294
-
295
- #chat .message-content {
296
- max-width: 100% !important;
297
- width: 100% !important;
298
- margin: 0 !important;
299
- padding: 0 !important;
300
- display: flex !important;
301
- gap: 16px !important;
302
- align-items: flex-start !important;
303
- color: black !important;
304
- }
305
-
306
- #chat .avatar {
307
- width: 36px !important;
308
- height: 36px !important;
309
- border-radius: 50% !important;
310
- flex-shrink: 0 !important;
311
- background: var(--accent) !important;
312
- display: flex !important;
313
- align-items: center !important;
314
- justify-content: center !important;
315
  color: white !important;
316
- font-weight: 600 !important;
317
- font-size: 14px !important;
 
 
 
 
 
318
  }
319
-
320
- #chat .message-text {
321
- flex: 1 !important;
322
- color: var(--text-chat) !important;
323
- font-size: 16px !important;
 
 
 
 
324
  line-height: 1.6 !important;
325
- word-wrap: break-word !important;
326
- overflow-wrap: break-word !important;
327
- font-weight: 400 !important;
328
- max-width: calc(100% - 52px) !important;
329
- width: calc(100% - 52px) !important;
330
  }
331
-
332
- /* Melhor contraste para links e código */
333
- #chat .message-text a {
334
- color: var(--accent) !important;
335
- text-decoration: underline !important;
336
- }
337
-
338
- #chat code,
339
- #chat .message-text code,
340
- [data-testid="chatbot"] code,
341
- .gradio-container code {
342
- background: #f5f5f5 !important;
343
- color: #d73502 !important;
344
- padding: 2px 6px !important;
345
- border-radius: 4px !important;
346
- font-family: 'Monaco', 'Consolas', 'Courier New', monospace !important;
347
- font-size: 14px !important;
348
- border: 1px solid #e0e0e0 !important;
349
- }
350
-
351
- #chat pre,
352
- #chat .message-text pre,
353
- [data-testid="chatbot"] pre,
354
- .gradio-container pre {
355
- background: #f8f8f8 !important;
356
- color: #2d2d2d !important;
357
- border: 1px solid #e0e0e0 !important;
358
  border-radius: 8px !important;
359
  padding: 16px !important;
360
- overflow-x: auto !important;
361
- max-width: 100% !important;
362
  margin: 12px 0 !important;
363
- font-family: 'Monaco', 'Consolas', 'Courier New', monospace !important;
 
364
  font-size: 14px !important;
365
- line-height: 1.4 !important;
366
- }
367
-
368
- #chat .message-text strong {
369
- color: var(--text-chat) !important;
370
- font-weight: 600 !important;
371
  }
372
-
373
- /* Área de Input */
374
- .input-area {
375
- padding: 16px 20px;
376
- background: var(--bg-chat);
377
- border-top: 1px solid var(--border-color);
378
- position: relative;
379
- flex-shrink: 0;
380
- height: var(--input-height);
381
- min-height: var(--input-height);
382
- max-height: var(--input-height);
383
- display: flex;
384
- align-items: center;
385
- width: 100%;
386
  }
387
-
388
- .input-container {
389
- width: 100% !important;
390
- max-width: 100% !important;
391
- margin: 0 !important;
392
- position: relative;
393
- background: var(--bg-chat);
394
- border: 2px solid var(--border-color);
395
- border-radius: var(--radius-lg);
396
- transition: all 0.2s ease;
397
- box-shadow: var(--shadow);
398
  }
399
-
400
- .input-container:focus-within {
401
- border-color: var(--accent);
402
- box-shadow: 0 0 0 3px rgba(16, 163, 127, 0.1);
403
  }
404
-
405
- .input-wrapper {
406
- display: flex;
407
- align-items: center;
408
- padding: 8px 12px;
409
- gap: 12px;
410
- width: 100%;
411
  }
412
-
413
- #entrada_usuario {
414
- flex: 1 !important;
415
- width: 100% !important;
416
  }
417
-
418
  #entrada_usuario textarea {
419
- background: var(--bg-chat) !important;
420
- border: none !important;
421
- color: var(--text-chat) !important;
422
- font-size: 16px !important;
423
  line-height: 1.5 !important;
424
- resize: none !important;
425
- padding: 8px 0 !important;
426
- height: 24px !important;
427
- max-height: 24px !important;
428
- overflow: hidden !important;
429
- font-family: inherit !important;
430
- width: 100% !important;
431
- }
432
-
433
-
434
- #entrada_usuario textarea::placeholder {
435
- color: var(--text-secondary) !important;
436
- font-size: 16px !important;
437
  }
438
-
439
  #entrada_usuario textarea:focus {
440
- outline: none !important;
441
- box-shadow: none !important;
442
  }
443
-
444
- .send-button {
445
- background: var(--accent) !important;
446
- color: white !important;
 
 
447
  border: none !important;
448
- border-radius: 10px !important;
449
- width: 20px !important;
450
- height: 40px !important;
451
- min-width: 20px !important;
452
- display: flex !important;
453
- align-items: center !important;
454
- justify-content: center !important;
455
  transition: all 0.2s ease !important;
456
- cursor: pointer !important;
457
- font-size: 16px !important;
458
- flex-shrink: 0 !important;
459
  }
460
-
461
- .send-button:hover:not(:disabled) {
462
- background: var(--accent-hover) !important;
463
- transform: scale(1.05) !important;
464
  }
465
-
466
- .send-button:disabled {
467
- background: #d1d5db !important;
468
- cursor: not-allowed !important;
469
- transform: none !important;
470
  }
471
-
472
- /* === RESPONSIVIDADE MOBILE === */
 
 
 
473
  @media (max-width: 768px) {
474
- :root {
475
- --header-height: 56px;
476
- --input-height: 70px;
477
- }
478
-
479
- .sidebar {
480
- position: fixed;
481
- top: 0;
482
- left: 0;
483
- height: 100vh !important;
484
- width: 280px !important;
485
- transform: translateX(-100%);
486
- z-index: 1000;
487
- box-shadow: var(--shadow-lg);
488
- }
489
-
490
- .sidebar.open {
491
- transform: translateX(0);
492
- }
493
-
494
- .chat-main {
495
- width: 100vw !important;
496
- max-width: 100vw !important;
497
- height: 100vh !important;
498
- max-height: 100vh !important;
499
- }
500
-
501
- .mobile-menu-btn {
502
- display: block !important;
503
- }
504
-
505
- .chat-header {
506
- padding: 12px 16px;
507
- height: var(--header-height);
508
- }
509
-
510
- .messages-container {
511
- height: calc(100vh - var(--header-height) - var(--input-height)) !important;
512
- max-height: calc(100vh - var(--header-height) - var(--input-height)) !important;
513
- padding: 0 !important;
514
- }
515
-
516
- #chat {
517
- padding: 0 !important;
518
- }
519
-
520
- #chat .message {
521
- padding: 16px !important;
522
- }
523
-
524
- #chat .message-content {
525
- max-width: 100% !important;
526
- width: 100% !important;
527
- margin: 0 !important;
528
- gap: 12px !important;
529
- }
530
-
531
- #chat .message-text {
532
- font-size: 15px !important;
533
- max-width: calc(100% - 48px) !important;
534
- width: calc(100% - 48px) !important;
535
- }
536
-
537
- #chat .avatar {
538
- width: 32px !important;
539
- height: 32px !important;
540
- }
541
-
542
- .input-area {
543
- padding: 12px 16px;
544
- height: var(--input-height);
545
  }
546
 
547
- .input-container {
548
- border-radius: var(--radius);
549
- width: 100% !important;
550
- max-width: 100% !important;
551
- }
552
-
553
- .input-wrapper {
554
- padding: 6px 8px;
555
- gap: 8px;
556
  }
557
 
558
- .send-button {
559
- width: 36px !important;
560
- height: 36px !important;
561
- min-width: 36px !important;
562
  }
563
 
564
- #entrada_usuario textarea {
565
- font-size: 16px !important;
 
566
  }
567
  }
568
-
569
- /* Overlay para mobile */
570
- .mobile-overlay {
571
- display: none;
572
- position: fixed;
573
- top: 0;
574
- left: 0;
575
- width: 100%;
576
- height: 100%;
577
- background: rgba(0, 0, 0, 0.5);
578
- z-index: 999;
579
  }
580
-
581
- .mobile-overlay.show {
582
- display: block;
583
- }
584
-
585
- /* === MELHORIAS GERAIS === */
586
- /* Scrollbar customizada */
587
- .messages-container::-webkit-scrollbar,
588
- #chat::-webkit-scrollbar {
589
- width: 6px;
590
- }
591
-
592
- .messages-container::-webkit-scrollbar-track,
593
- #chat::-webkit-scrollbar-track {
594
- background: transparent;
595
- }
596
-
597
- .messages-container::-webkit-scrollbar-thumb,
598
- #chat::-webkit-scrollbar-thumb {
599
- background: rgba(0, 0, 0, 0.2);
600
- border-radius: 3px;
601
- }
602
-
603
- .messages-container::-webkit-scrollbar-thumb:hover,
604
- #chat::-webkit-scrollbar-thumb:hover {
605
- background: rgba(0, 0, 0, 0.3);
606
- }
607
-
608
- /* Animações */
609
  @keyframes fadeInUp {
610
  from {
611
  opacity: 0;
@@ -616,343 +201,219 @@ body, .gradio-container {
616
  transform: translateY(0);
617
  }
618
  }
619
-
620
- #chat .message {
621
- animation: fadeInUp 0.3s ease-out;
622
  }
623
-
624
- /* Ocultar elementos desnecessários */
625
- footer {
626
- display: none !important;
627
  }
628
-
629
- .gr-button-lg {
630
- display: none !important;
631
  }
632
-
633
- /* Loading indicator */
634
- .typing-indicator {
635
- display: flex;
636
- align-items: center;
637
- gap: 4px;
638
- padding: 8px 0;
639
- color: var(--text-secondary);
640
  }
641
-
642
- .typing-indicator span {
643
- height: 8px;
644
- width: 8px;
645
- background: var(--text-secondary);
646
- border-radius: 50%;
647
- animation: typing 1.4s infinite ease-in-out;
648
  }
649
-
650
- .typing-indicator span:nth-child(2) {
651
- animation-delay: 0.2s;
 
 
652
  }
653
-
654
- .typing-indicator span:nth-child(3) {
655
- animation-delay: 0.4s;
 
656
  }
657
-
658
- @keyframes typing {
659
- 0%, 80%, 100% {
660
- opacity: 0.3;
661
- transform: scale(0.8);
662
- }
663
- 40% {
664
- opacity: 1;
665
- transform: scale(1);
666
- }
667
  }
668
-
669
- /* Forçar uso total da viewport */
670
- .gradio-container,
671
- .gradio-container > div,
672
- .gradio-container > div > div {
673
- height: 100vh !important;
674
- max-height: 100vh !important;
 
 
 
 
 
675
  width: 100% !important;
676
- max-width: 100% !important;
677
- overflow: hidden !important;
678
- padding: 0 !important;
679
- margin: 0 !important;
 
 
 
 
 
 
680
  }
681
  """
682
 
683
  def criar_interface():
684
- with gr.Blocks(theme=gr.themes.Base(), css=css_customizado, title="iAldo AI Assistant") as interface:
685
- session_id_state = gr.State(lambda: str(uuid.uuid4()))
686
-
687
- with gr.Row(elem_classes="main-container"):
688
- # === SIDEBAR ===
689
- with gr.Column(scale=0, min_width=280, elem_classes="sidebar", elem_id="sidebar"):
690
- with gr.Group():
691
- gr.HTML("""
692
- <div class='sidebar-header'>
693
- <div class='sidebar-title'>iAldo AI</div>
694
- <div class='sidebar-subtitle'>Assistant Inteligente</div>
695
- </div>
696
- """)
697
- novo_chat_btn = gr.Button("✨ Novo Chat", elem_classes="new-chat-btn")
698
-
699
- with gr.Group(elem_classes="sidebar-section"):
700
- gr.HTML("<p class='sidebar-section-title'>🤖 Modelo de IA</p>")
701
- modelo_select = gr.Dropdown(
702
- choices=list(MODELS.keys()),
703
- value=DEFAULT_MODEL,
704
- label=None,
705
- show_label=False,
706
- container=False
707
- )
708
-
709
- with gr.Accordion("ℹ️ Informações", open=False):
710
- gr.Markdown("""
711
- **Assistente do Prof. Dr. Aldo Henrique**
712
-
713
- 🎯 **Especialidades:**
714
- - Programação C/C++, Java
715
- - Desenvolvimento Web
716
- - Inteligência Artificial
717
- - Algoritmos e Estruturas de Dados
718
-
719
- 🌐 **Website:** [aldohenrique.com.br](https://aldohenrique.com.br)
720
-
721
- 💡 **Dica:** Use Shift+Enter para quebrar linha
722
- """)
723
-
724
- # === ÁREA PRINCIPAL ===
725
- with gr.Column(scale=4, elem_classes="chat-main"):
726
- # Header do Chat
727
- gr.HTML("""
728
- <div class='chat-header'>
729
- <button class='mobile-menu-btn' onclick='toggleSidebar()'>☰</button>
730
- <div class='chat-header-title'>Chat com Dr. Aldo</div>
731
- <div></div>
732
- </div>
733
- """)
734
-
735
- # Container das mensagens
736
- with gr.Column(elem_classes="messages-container"):
737
  chatbot = gr.Chatbot(
738
- [],
739
- label="",
740
  elem_id="chat",
741
- show_label=False,
742
- container=False,
743
- avatar_images=(
744
- "https://api.dicebear.com/7.x/initials/svg?seed=User&backgroundColor=6366f1",
745
- "https://api.dicebear.com/7.x/bottts/svg?seed=Aldo&backgroundColor=10a37f"
746
- ),
747
- bubble_full_width=False,
748
  height="100%",
749
- show_copy_button=True
 
 
 
 
 
750
  )
751
 
752
- # Área de Input
753
- with gr.Column(elem_classes="input-area"):
754
- with gr.Row(elem_classes="input-container"):
755
- with gr.Row(elem_classes="input-wrapper"):
756
- user_input = gr.Textbox(
757
- show_label=False,
758
- placeholder="Digite sua mensagem para o Dr. Aldo...",
759
- elem_id="entrada_usuario",
760
- container=False,
761
- scale=10,
762
- lines=1,
763
- max_lines=1
764
- )
765
- enviar_btn = gr.Button("", variant="primary", elem_classes="send-button", scale=1, min_width=40)
766
-
767
- # Overlay para mobile
768
- gr.HTML('<div class="mobile-overlay" onclick="toggleSidebar()"></div>', elem_id="mobile-overlay")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
769
 
770
- # === LÓGICA DE BACKEND (mantida intacta) ===
771
  def responder(chat_history, user_msg, modelo, session_id):
772
  if not user_msg.strip():
773
  return chat_history, ""
774
-
775
- chat_history.append([user_msg, None])
 
776
  yield chat_history, ""
777
 
778
  try:
779
- resposta_stream = responder_como_aldo(session_id, user_msg, modelo)
 
 
 
 
 
780
 
781
- resposta_completa = ""
782
- for chunk in resposta_stream:
783
- resposta_completa += chunk
784
- chat_history[-1][1] = resposta_completa
785
- yield chat_history, ""
786
-
787
  except Exception as e:
788
- chat_history[-1][1] = f"❌ Desculpe, ocorreu um erro: {str(e)}"
 
789
  yield chat_history, ""
790
 
791
- def limpar_chat():
792
- return [], str(uuid.uuid4())
793
-
794
- # === EVENTOS (mantidos intactos) ===
795
- user_input.submit(
796
  fn=responder,
797
  inputs=[chatbot, user_input, modelo_select, session_id_state],
798
- outputs=[chatbot, user_input]
 
799
  )
800
-
801
- enviar_btn.click(
802
  fn=responder,
803
  inputs=[chatbot, user_input, modelo_select, session_id_state],
804
- outputs=[chatbot, user_input]
805
- )
806
-
807
- novo_chat_btn.click(
808
- fn=limpar_chat,
809
- inputs=[],
810
- outputs=[chatbot, session_id_state]
811
  )
812
 
813
- # === JAVASCRIPT APRIMORADO ===
814
- interface.load(
815
- None,
816
- None,
817
- None,
818
- js="""
819
- () => {
820
- // Função para toggle da sidebar no mobile
821
- window.toggleSidebar = function() {
822
- const sidebar = document.getElementById('sidebar');
823
- const overlay = document.getElementById('mobile-overlay');
824
-
825
- if (sidebar && overlay) {
826
- sidebar.classList.toggle('open');
827
- overlay.classList.toggle('show');
828
- }
829
- }
830
-
831
- // Scroll automático para o final do chat
832
- function scrollChatToBottom() {
833
- const chatContainer = document.querySelector('.messages-container');
834
- if (chatContainer) {
835
- chatContainer.scrollTo({
836
- top: chatContainer.scrollHeight,
837
- behavior: 'smooth'
838
- });
839
- }
840
- }
841
-
842
- // Observer para novas mensagens
843
- const observer = new MutationObserver((mutations) => {
844
- let shouldScroll = false;
845
- mutations.forEach(mutation => {
846
- if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
847
- shouldScroll = true;
848
- }
849
- });
850
- if (shouldScroll) {
851
- setTimeout(scrollChatToBottom, 100);
852
- }
853
- });
854
-
855
- const chatElement = document.getElementById('chat');
856
- if (chatElement) {
857
- observer.observe(chatElement, {
858
- childList: true,
859
- subtree: true,
860
- attributes: true,
861
- attributeFilter: ['class']
862
- });
863
- }
864
 
865
- // Gerenciamento do input
866
- const userInput = document.getElementById('entrada_usuario');
867
- if (userInput) {
868
- const textarea = userInput.querySelector('textarea');
869
- if (textarea) {
870
- // Envio com Enter (Shift+Enter para nova linha)
871
- textarea.addEventListener('keydown', (e) => {
872
- if (e.key === 'Enter' && !e.shiftKey) {
873
- e.preventDefault();
874
- const sendButton = document.querySelector('.send-button');
875
- if (sendButton && textarea.value.trim()) {
876
- sendButton.click();
877
- }
878
- }
879
  });
880
-
881
- // Foco inicial
882
- setTimeout(() => textarea.focus(), 500);
883
- }
884
- }
885
-
886
- // Fechar sidebar ao clicar fora (mobile)
887
- document.addEventListener('click', (e) => {
888
- if (window.innerWidth <= 768) {
889
- const sidebar = document.getElementById('sidebar');
890
- const menuBtn = document.querySelector('.mobile-menu-btn');
891
-
892
- if (sidebar && sidebar.classList.contains('open') &&
893
- !sidebar.contains(e.target) &&
894
- !menuBtn.contains(e.target)) {
895
- toggleSidebar();
896
- }
897
- }
898
- });
899
-
900
- // Gerenciar responsividade
901
- function handleResize() {
902
- if (window.innerWidth > 768) {
903
- const sidebar = document.getElementById('sidebar');
904
- const overlay = document.getElementById('mobile-overlay');
905
- if (sidebar) sidebar.classList.remove('open');
906
- if (overlay) overlay.classList.remove('show');
907
- }
908
  }
909
-
910
- window.addEventListener('resize', handleResize);
911
-
912
- // Scroll inicial e foco
913
- setTimeout(() => {
914
- scrollChatToBottom();
915
- const textarea = document.querySelector('#entrada_usuario textarea');
916
- if (textarea) textarea.focus();
917
- }, 1000);
918
-
919
- console.log('🚀 iAldo AI Interface carregada com sucesso!');
920
- }
921
- """
922
- )
923
 
924
  return interface
925
 
926
- # === CÓDIGO DE INICIALIZAÇÃO (mantido intacto) ===
927
- def inicializar_sistema_sync():
928
- """Função síncrona para compatibilidade"""
929
- try:
930
- import asyncio
931
- try:
932
- loop = asyncio.get_event_loop()
933
- if loop.is_running():
934
- import concurrent.futures
935
- with concurrent.futures.ThreadPoolExecutor() as executor:
936
- future = executor.submit(lambda: asyncio.run(inicializar_sistema()))
937
- return future.result()
938
- else:
939
- return loop.run_until_complete(inicializar_sistema())
940
- except RuntimeError:
941
- return asyncio.run(inicializar_sistema())
942
- except Exception as e:
943
- print(f"Erro na inicialização: {e}")
944
- return False, {}
945
-
946
  def configurar_interface():
947
  """
948
- Configura a interface Gradio apenas se o sistema for inicializado com sucesso.
 
949
  """
950
  try:
951
- status, available_models = inicializar_sistema()
952
  if status:
953
  return criar_interface()
954
  else:
955
- error_msg = f"Sistema não inicializado: Modelos indisponíveis. Modelos: {', '.join(available_models.keys()) if available_models else 'Nenhum'}"
956
  raise RuntimeError(error_msg)
957
  except Exception as e:
958
  print(f"Erro na configuração da interface: {e}")
@@ -969,5 +430,5 @@ if __name__ == "__main__":
969
  show_error=True
970
  )
971
  except Exception as e:
972
- print(f"Erro ao iniciar a aplicação: {e} ")
973
  exit(1)
 
8
  inicializar_sistema
9
  )
10
 
 
11
  css_customizado = """
12
+ .gradio-container {
13
+ max-width: 1400px !important;
14
+ margin: 0 auto;
15
+ width: 99%;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  height: 100vh !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  display: flex;
18
  flex-direction: column;
19
+ overflow: hidden;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  }
21
+ .main-content {
22
+ display: flex;
23
+ flex-direction: column;
24
+ height: 100vh;
25
+ overflow: hidden;
26
  flex-shrink: 0;
27
  }
28
+ .titulo-principal {
29
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
 
 
 
 
 
 
 
 
 
 
 
30
  color: white !important;
31
+ padding: 10px !important;
32
+ border-radius: 10px !important;
33
+ margin-bottom: 10px !important;
34
+ text-align: center !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  flex-shrink: 0;
 
 
 
36
  }
37
+ .chat-area {
38
+ flex: 1;
39
+ display: flex;
40
+ flex-direction: column;
41
+ overflow: hidden;
42
  }
43
+ .chat-container {
44
+ flex: 1;
45
+ overflow-y: auto;
46
+ margin-bottom: 10px;
 
 
 
 
 
 
47
  }
48
+ .input-container {
49
+ flex-shrink: 0;
50
+ padding: 10px 0;
51
+ display: flex;
52
+ flex-direction: column;
53
+ justify-content: center;
54
  }
55
+ .additional-content {
56
+ overflow-y: auto;
57
+ padding-top: 20px;
 
 
 
 
 
 
 
 
 
 
58
  }
59
+ /* Estilos para o chat - Melhorias na legibilidade */
60
+ .chatbot {
 
61
  height: 100% !important;
62
+ max-height: none !important;
 
 
 
 
 
 
 
 
 
 
 
 
63
  }
64
+ /* Mensagens do usuário */
65
+ .message.user {
66
+ background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%) !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  color: white !important;
68
+ border-radius: 18px 18px 6px 18px !important;
69
+ padding: 12px 16px !important;
70
+ margin: 8px 0 !important;
71
+ font-size: 15px !important;
72
+ line-height: 1.5 !important;
73
+ box-shadow: 0 2px 8px rgba(79, 70, 229, 0.3) !important;
74
+ border: none !important;
75
  }
76
+ /* Mensagens do bot */
77
+ .message.bot {
78
+ background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%) !important;
79
+ color: #1e293b !important;
80
+ border: 1px solid #e2e8f0 !important;
81
+ border-radius: 18px 18px 18px 6px !important;
82
+ padding: 16px 20px !important;
83
+ margin: 8px 0 !important;
84
+ font-size: 15px !important;
85
  line-height: 1.6 !important;
86
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05) !important;
 
 
 
 
87
  }
88
+ /* Estilização para código dentro das mensagens */
89
+ .message pre {
90
+ background: #1e293b !important;
91
+ color: #e2e8f0 !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  border-radius: 8px !important;
93
  padding: 16px !important;
 
 
94
  margin: 12px 0 !important;
95
+ overflow-x: auto !important;
96
+ font-family: 'Fira Code', 'Monaco', 'Menlo', 'Ubuntu Mono', monospace !important;
97
  font-size: 14px !important;
98
+ line-height: 1.5 !important;
99
+ border: 1px solid #374151 !important;
 
 
 
 
100
  }
101
+ .message code {
102
+ background: #e2e8f0 !important;
103
+ color: #1e293b !important;
104
+ padding: 2px 6px !important;
105
+ border-radius: 4px !important;
106
+ font-family: 'Fira Code', 'Monaco', 'Menlo', 'Ubuntu Mono', monospace !important;
107
+ font-size: 13px !important;
 
 
 
 
 
 
 
108
  }
109
+ /* Código inline dentro de pre */
110
+ .message pre code {
111
+ background: transparent !important;
112
+ color: #e2e8f0 !important;
113
+ padding: 0 !important;
114
+ border-radius: 0 !important;
 
 
 
 
 
115
  }
116
+ /* Estilos específicos do Gradio para chatbot */
117
+ .chatbot .message-wrap {
118
+ margin: 8px 0 !important;
 
119
  }
120
+ .chatbot .message-wrap.user {
121
+ justify-content: flex-end !important;
 
 
 
 
 
122
  }
123
+ .chatbot .message-wrap.bot {
124
+ justify-content: flex-start !important;
 
 
125
  }
126
+ /* Melhorias na área de input */
127
  #entrada_usuario textarea {
128
+ background: linear-gradient(135deg, #1e293b 0%, #374151 100%) !important;
129
+ color: white !important;
130
+ font-size: 15px !important;
 
131
  line-height: 1.5 !important;
132
+ border: 2px solid #374151 !important;
133
+ border-radius: 12px !important;
134
+ padding: 12px 16px !important;
135
+ min-height: 60px !important;
136
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1) !important;
 
 
 
 
 
 
 
 
137
  }
 
138
  #entrada_usuario textarea:focus {
139
+ border-color: #4f46e5 !important;
140
+ box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1) !important;
141
  }
142
+ #entrada_usuario textarea::placeholder {
143
+ color: #9ca3af !important;
144
+ }
145
+ /* Botão de enviar */
146
+ .gradio-button.primary {
147
+ background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%) !important;
148
  border: none !important;
149
+ border-radius: 12px !important;
150
+ padding: 12px 24px !important;
151
+ font-weight: 600 !important;
152
+ font-size: 15px !important;
 
 
 
153
  transition: all 0.2s ease !important;
 
 
 
154
  }
155
+ .gradio-button.primary:hover {
156
+ transform: translateY(-1px) !important;
157
+ box-shadow: 0 4px 12px rgba(79, 70, 229, 0.4) !important;
 
158
  }
159
+ /* Dropdown do modelo */
160
+ .modelo-dropdown {
161
+ margin-bottom: 15px !important;
 
 
162
  }
163
+ .modelo-dropdown .gr-dropdown {
164
+ border-radius: 8px !important;
165
+ border: 1px solid #d1d5db !important;
166
+ }
167
+ /* Responsividade melhorada */
168
  @media (max-width: 768px) {
169
+ .titulo-principal {
170
+ padding: 8px !important;
171
+ font-size: 14px !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172
  }
173
 
174
+ #entrada_usuario textarea {
175
+ min-height: 50px !important;
176
+ font-size: 16px !important;
 
 
 
 
 
 
177
  }
178
 
179
+ .message.user,
180
+ .message.bot {
181
+ font-size: 14px !important;
182
+ padding: 10px 14px !important;
183
  }
184
 
185
+ .message pre {
186
+ font-size: 12px !important;
187
+ padding: 12px !important;
188
  }
189
  }
190
+ /* Animações suaves */
191
+ .message {
192
+ animation: fadeInUp 0.3s ease-out !important;
 
 
 
 
 
 
 
 
193
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
  @keyframes fadeInUp {
195
  from {
196
  opacity: 0;
 
201
  transform: translateY(0);
202
  }
203
  }
204
+ /* Melhorias gerais na tipografia */
205
+ .chatbot {
206
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', sans-serif !important;
207
  }
208
+ /* Scroll personalizado para o chat */
209
+ .chat-container::-webkit-scrollbar {
210
+ width: 6px;
 
211
  }
212
+ .chat-container::-webkit-scrollbar-track {
213
+ background: #f1f5f9;
214
+ border-radius: 3px;
215
  }
216
+ .chat-container::-webkit-scrollbar-thumb {
217
+ background: #cbd5e1;
218
+ border-radius: 3px;
 
 
 
 
 
219
  }
220
+ .chat-container::-webkit-scrollbar-thumb:hover {
221
+ background: #94a3b8;
 
 
 
 
 
222
  }
223
+ /* Força aplicação dos estilos */
224
+ #component-6 { flex-grow: initial !important; }
225
+ #component-7 { flex-grow: initial !important; }
226
+ .message-wrap.svelte-gjtrl6 .prose.chatbot.md {
227
+ opacity: 1 !important;
228
  }
229
+ /* Estilo para links */
230
+ .message a {
231
+ color: #4f46e5 !important;
232
+ text-decoration: underline !important;
233
  }
234
+ .message.user a {
235
+ color: #e0e7ff !important;
 
 
 
 
 
 
 
 
236
  }
237
+ /* Estilo para listas */
238
+ .message ul, .message ol {
239
+ margin: 12px 0 !important;
240
+ padding-left: 20px !important;
241
+ }
242
+ .message li {
243
+ margin: 6px 0 !important;
244
+ line-height: 1.6 !important;
245
+ }
246
+ /* Estilo para tabelas */
247
+ .message table {
248
+ border-collapse: collapse !important;
249
  width: 100% !important;
250
+ margin: 12px 0 !important;
251
+ }
252
+ .message th, .message td {
253
+ border: 1px solid #d1d5db !important;
254
+ padding: 8px 12px !important;
255
+ text-align: left !important;
256
+ }
257
+ .message th {
258
+ background: #f8fafc !important;
259
+ font-weight: 600 !important;
260
  }
261
  """
262
 
263
  def criar_interface():
264
+ with gr.Blocks(title="Dr. Aldo Henrique - API Externa", theme=gr.themes.Soft(), css=css_customizado) as interface:
265
+ session_id_state = gr.State(str(uuid.uuid4())) # Geração do session_id único
266
+
267
+ with gr.Column(elem_classes="main-content"):
268
+ gr.HTML("""
269
+ <div class="titulo-principal">
270
+ <h4 style="margin: 0;">🤖 iAldo - Converse com o <a href="https://aldohenrique.com.br/" style="color: white; text-decoration: underline;">Prof. Dr. Aldo Henrique</a></h4>
271
+ </div>
272
+ """)
273
+
274
+ with gr.Column(elem_classes="chat-area"):
275
+ with gr.Column(elem_classes="chat-container"):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
276
  chatbot = gr.Chatbot(
277
+ label="💬 Área do chat",
 
278
  elem_id="chat",
 
 
 
 
 
 
 
279
  height="100%",
280
+ show_label=False,
281
+ container=True,
282
+ scale=1,
283
+ min_width=160,
284
+ visible=True,
285
+ elem_classes="chatbot"
286
  )
287
 
288
+ with gr.Column(elem_classes="input-container"):
289
+ with gr.Row():
290
+ modelo_select = gr.Dropdown(
291
+ choices=list(MODELS.keys()),
292
+ value=DEFAULT_MODEL,
293
+ label="🧠 Selecione o Modelo de Pensamento",
294
+ elem_classes="modelo-dropdown"
295
+ )
296
+ with gr.Row():
297
+ user_input = gr.Textbox(
298
+ show_label=False,
299
+ placeholder="Digite sua pergunta e pressione Enter ou clique em Enviar",
300
+ lines=2,
301
+ elem_id="entrada_usuario",
302
+ max_lines=6
303
+ )
304
+ enviar_btn = gr.Button("Enviar", variant="primary", size="lg")
305
+
306
+ with gr.Column(elem_classes="additional-content"):
307
+ with gr.Accordion("⚙️ Controle do Conhecimento (RAG)", open=False):
308
+ status_rag = gr.Textbox(label="Status do Retreino", interactive=False)
309
+ botao_retreinar = gr.Button("🔄 Atualizar Conhecimento do Blog", variant="stop")
310
+ download_faiss_file = gr.File(label="Download do Índice FAISS", interactive=False, file_count="single", file_types=[".pkl"])
311
+ download_urls_file = gr.File(label="Download das URLs Processadas", interactive=False, file_count="single", file_types=[".pkl"])
312
+
313
+ with gr.Accordion("📚 Exemplos de Perguntas", open=False):
314
+ gr.Examples(
315
+ examples=[
316
+ ["Como implementar uma lista ligada em C com todas as operações básicas?", DEFAULT_MODEL],
317
+ ["Qual a sua opinião sobre o uso de ponteiros em C++ moderno, baseada no seu blog?", "Mistral 7B (Mais acertivo)"],
318
+ ["Resuma o que você escreveu sobre machine learning no seu blog.", "Zephyr 7B (Meio Termo)"],
319
+ ],
320
+ inputs=[user_input, modelo_select]
321
+ )
322
+
323
+ with gr.Accordion("🔧 Status da API", open=False):
324
+ status_api = gr.Textbox(label="Status dos Modelos", interactive=False, lines=8,
325
+ value="Modelos carregados com sucesso! Verifique o console para detalhes.")
326
+
327
+ with gr.Accordion("ℹ️ Informações", open=False):
328
+ gr.Markdown("""
329
+ ### Sobre o Dr. Aldo Henrique:
330
+ - **Especialidade**: Linguagens C, Java, Desenvolvimento Web, Inteligência Artificial
331
+ - **Conhecimento Adicional**: Conteúdo do blog aldohenrique.com.br
332
+ ### Dicas para melhores respostas:
333
+ - Faça perguntas específicas sobre o conteúdo do blog para ver o RAG em ação!
334
+ - Peça resumos ou opiniões sobre temas que o professor aborda.
335
+
336
+ ### Melhorias na Interface:
337
+ - **Mensagens do usuário**: Estilo moderno com gradiente azul/roxo
338
+ - **Respostas do bot**: Fundo claro com excelente contraste para leitura
339
+ - **Códigos**: Syntax highlighting com fundo escuro e fonte monospace
340
+ - **Responsivo**: Otimizado para desktop e mobile
341
+ """)
342
 
 
343
  def responder(chat_history, user_msg, modelo, session_id):
344
  if not user_msg.strip():
345
  return chat_history, ""
346
+
347
+ # Adiciona a mensagem do usuário ao histórico
348
+ chat_history = chat_history + [[user_msg, "🤖 Dr. Aldo Henrique está digitando..."]]
349
  yield chat_history, ""
350
 
351
  try:
352
+ # Obtem a resposta do modelo
353
+ resposta_final = responder_como_aldo(session_id, user_msg, modelo)
354
+
355
+ # Atualiza o histórico com a resposta final
356
+ chat_history[-1][1] = resposta_final
357
+ yield chat_history, ""
358
 
 
 
 
 
 
 
359
  except Exception as e:
360
+ # Em caso de erro, mostra uma mensagem amigável
361
+ chat_history[-1][1] = f"❌ Desculpe, ocorreu um erro ao processar sua mensagem: {str(e)}"
362
  yield chat_history, ""
363
 
364
+ # Eventos de clique e submit
365
+ enviar_btn.click(
 
 
 
366
  fn=responder,
367
  inputs=[chatbot, user_input, modelo_select, session_id_state],
368
+ outputs=[chatbot, user_input],
369
+ show_progress=True
370
  )
371
+
372
+ user_input.submit(
373
  fn=responder,
374
  inputs=[chatbot, user_input, modelo_select, session_id_state],
375
+ outputs=[chatbot, user_input],
376
+ show_progress=True
 
 
 
 
 
377
  )
378
 
379
+ botao_retreinar.click(
380
+ fn=build_and_save_vector_store,
381
+ outputs=[status_rag, download_faiss_file, download_urls_file],
382
+ show_progress=True
383
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
384
 
385
+ # Script para focar no input ao carregar a página
386
+ gr.HTML("""
387
+ <script>
388
+ window.addEventListener("load", function() {
389
+ const textarea = document.querySelector("#entrada_usuario textarea");
390
+ if (textarea) {
391
+ setTimeout(() => {
392
+ textarea.focus();
393
+ // Adiciona evento para redimensionar automaticamente
394
+ textarea.addEventListener('input', function() {
395
+ this.style.height = 'auto';
396
+ this.style.height = this.scrollHeight + 'px';
 
 
397
  });
398
+ }, 100);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
399
  }
400
+ });
401
+ </script>
402
+ """)
 
 
 
 
 
 
 
 
 
 
 
403
 
404
  return interface
405
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
406
  def configurar_interface():
407
  """
408
+ Configura a interface Gradio apenas se o sistema for inicializado com pelo menos 3 modelos disponíveis.
409
+ Lança uma exceção com a lista de modelos disponíveis se a inicialização falhar.
410
  """
411
  try:
412
+ status, available_models = inicializar_sistema_sync()
413
  if status:
414
  return criar_interface()
415
  else:
416
+ error_msg = f"Não foi possível inicializar o sistema: menos de 3 modelos de IA disponíveis. Modelos disponíveis: {', '.join(available_models.keys()) if available_models else 'Nenhum'}"
417
  raise RuntimeError(error_msg)
418
  except Exception as e:
419
  print(f"Erro na configuração da interface: {e}")
 
430
  show_error=True
431
  )
432
  except Exception as e:
433
+ print(f"Erro ao iniciar a aplicação: {e}")
434
  exit(1)