Spaces:
				
			
			
	
			
			
					
		Running
		
	
	
	
			
			
	
	
	
	
		
		
					
		Running
		
	Update app.py
Browse files
    	
        app.py
    CHANGED
    
    | @@ -2,6 +2,9 @@ import streamlit as st | |
| 2 | 
             
            import streamlit_authenticator as stauth
         | 
| 3 | 
             
            import sqlite3
         | 
| 4 | 
             
            import os
         | 
|  | |
|  | |
|  | |
| 5 | 
             
            from transformers import pipeline, AutoModelForCausalLM, AutoTokenizer
         | 
| 6 | 
             
            import torch
         | 
| 7 | 
             
            from PIL import Image
         | 
| @@ -12,6 +15,8 @@ import logging | |
| 12 | 
             
            import tempfile
         | 
| 13 | 
             
            from streamlit.runtime.uploaded_file_manager import UploadedFile
         | 
| 14 | 
             
            from diffusers import StableDiffusionPipeline
         | 
|  | |
|  | |
| 15 |  | 
| 16 | 
             
            # Configurar página
         | 
| 17 | 
             
            st.set_page_config(
         | 
| @@ -20,43 +25,42 @@ st.set_page_config( | |
| 20 | 
             
                layout="wide"
         | 
| 21 | 
             
            )
         | 
| 22 |  | 
| 23 | 
            -
            # Configurar logging
         | 
|  | |
| 24 | 
             
            logging.basicConfig(
         | 
| 25 | 
            -
                filename='app_errors.log',
         | 
| 26 | 
             
                level=logging.ERROR,
         | 
| 27 | 
             
                format='%(asctime)s - %(levelname)s - %(message)s'
         | 
| 28 | 
             
            )
         | 
| 29 |  | 
| 30 | 
            -
            # Configurar banco de dados | 
| 31 | 
             
            def init_db():
         | 
| 32 | 
             
                """Inicializa o banco de dados SQLite com tabela de usuários"""
         | 
| 33 | 
            -
                db_path = os.getenv('DB_PATH', 'users.db')
         | 
|  | |
| 34 | 
             
                conn = sqlite3.connect(db_path)
         | 
| 35 | 
             
                cursor = conn.cursor()
         | 
| 36 |  | 
| 37 | 
            -
                # Criar tabela de usuários se não existir
         | 
| 38 | 
             
                cursor.execute('''
         | 
| 39 | 
             
                    CREATE TABLE IF NOT EXISTS users (
         | 
| 40 | 
             
                        username TEXT PRIMARY KEY,
         | 
| 41 | 
             
                        name TEXT NOT NULL,
         | 
| 42 | 
            -
                        password TEXT NOT NULL
         | 
|  | |
| 43 | 
             
                    )
         | 
| 44 | 
             
                ''')
         | 
| 45 |  | 
| 46 | 
            -
                # Adicionar  | 
| 47 | 
             
                try:
         | 
| 48 | 
            -
                    hashed_password = stauth.Hasher([' | 
| 49 | 
             
                    cursor.execute('''
         | 
| 50 | 
            -
                        INSERT OR IGNORE INTO users (username, name, password)
         | 
| 51 | 
            -
                        VALUES (?, ?, ?)
         | 
| 52 | 
            -
                    ''', (' | 
| 53 | 
            -
                    cursor.execute('''
         | 
| 54 | 
            -
                        INSERT OR IGNORE INTO users (username, name, password)
         | 
| 55 | 
            -
                        VALUES (?, ?, ?)
         | 
| 56 | 
            -
                    ''', ('empresa1', 'Empresa Um', hashed_password))
         | 
| 57 | 
             
                    conn.commit()
         | 
| 58 | 
             
                except Exception as e:
         | 
| 59 | 
             
                    logging.error(f"Erro ao inicializar banco de dados: {e}")
         | 
|  | |
| 60 | 
             
                    st.error(f"Erro ao inicializar banco de dados: {str(e)}")
         | 
| 61 |  | 
| 62 | 
             
                conn.close()
         | 
| @@ -64,11 +68,11 @@ def init_db(): | |
| 64 | 
             
            def load_users_from_db():
         | 
| 65 | 
             
                """Carrega usuários do banco de dados SQLite"""
         | 
| 66 | 
             
                try:
         | 
| 67 | 
            -
                    db_path = os.getenv('DB_PATH', 'users.db')
         | 
| 68 | 
             
                    conn = sqlite3.connect(db_path)
         | 
| 69 | 
             
                    cursor = conn.cursor()
         | 
| 70 | 
            -
                    cursor.execute("SELECT username, name, password FROM users")
         | 
| 71 | 
            -
                    users = {row[0]: {'name': row[1], 'password': row[2]} for row in cursor.fetchall()}
         | 
| 72 | 
             
                    conn.close()
         | 
| 73 |  | 
| 74 | 
             
                    config = {
         | 
| @@ -78,130 +82,64 @@ def load_users_from_db(): | |
| 78 | 
             
                    }
         | 
| 79 | 
             
                    return config
         | 
| 80 | 
             
                except Exception as e:
         | 
| 81 | 
            -
                    st.error(f"Erro ao carregar usuários | 
| 82 | 
             
                    logging.error(f"Erro ao carregar usuários: {e}")
         | 
|  | |
| 83 | 
             
                    return None
         | 
| 84 |  | 
| 85 | 
            -
            # Cache para  | 
| 86 | 
             
            @st.cache_resource(show_spinner=False)
         | 
| 87 | 
            -
            def  | 
| 88 | 
            -
                """Carrega  | 
| 89 | 
            -
                device = torch.device(" | 
| 90 | 
            -
                 | 
| 91 | 
            -
                 | 
|  | |
| 92 |  | 
| 93 | 
             
                try:
         | 
| 94 | 
            -
                     | 
| 95 | 
            -
             | 
| 96 | 
            -
             | 
| 97 | 
            -
                        model=" | 
| 98 | 
            -
             | 
| 99 | 
            -
             | 
| 100 | 
            -
                    
         | 
| 101 | 
            -
             | 
| 102 | 
            -
             | 
| 103 | 
            -
                        model=" | 
| 104 | 
            -
             | 
| 105 | 
            -
             | 
| 106 | 
            -
             | 
| 107 | 
            -
             | 
| 108 | 
            -
                        " | 
| 109 | 
            -
             | 
| 110 | 
            -
                        device=device,
         | 
| 111 | 
            -
             | 
| 112 | 
            -
                         | 
| 113 | 
            -
                     | 
| 114 | 
            -
             | 
| 115 | 
            -
                     | 
| 116 | 
            -
                        " | 
| 117 | 
            -
             | 
| 118 | 
            -
                        device=device
         | 
| 119 | 
            -
                     | 
| 120 | 
            -
             | 
| 121 | 
            -
                     | 
| 122 | 
            -
                        " | 
| 123 | 
            -
             | 
| 124 | 
            -
                         | 
| 125 | 
            -
             | 
| 126 | 
            -
             | 
| 127 | 
            -
                    tokenizer_gpt2 = AutoTokenizer.from_pretrained("gpt2")
         | 
| 128 | 
            -
                    model_gpt2 = AutoModelForCausalLM.from_pretrained("gpt2")
         | 
| 129 | 
            -
                    model_gpt2.config.pad_token_id = model_gpt2.config.eos_token_id
         | 
| 130 | 
            -
                    
         | 
| 131 | 
            -
                    models['text_generation'] = pipeline(
         | 
| 132 | 
            -
                        "text-generation",
         | 
| 133 | 
            -
                        model=model_gpt2,
         | 
| 134 | 
            -
                        tokenizer=tokenizer_gpt2,
         | 
| 135 | 
            -
                        device=device
         | 
| 136 | 
            -
                    )
         | 
| 137 | 
            -
                    
         | 
| 138 | 
            -
                    models['ner'] = pipeline(
         | 
| 139 | 
            -
                        "ner",
         | 
| 140 | 
            -
                        model="dbmdz/bert-large-cased-finetuned-conll03-english",
         | 
| 141 | 
            -
                        device=device,
         | 
| 142 | 
            -
                        aggregation_strategy="simple"
         | 
| 143 | 
            -
                    )
         | 
| 144 | 
            -
                    
         | 
| 145 | 
            -
                    # Modelos de imagem
         | 
| 146 | 
            -
                    models['image_classification'] = pipeline(
         | 
| 147 | 
            -
                        "image-classification",
         | 
| 148 | 
            -
                        model="google/vit-base-patch16-224",
         | 
| 149 | 
            -
                        device=device
         | 
| 150 | 
            -
                    )
         | 
| 151 | 
            -
                    
         | 
| 152 | 
            -
                    models['object_detection'] = pipeline(
         | 
| 153 | 
            -
                        "object-detection",
         | 
| 154 | 
            -
                        model="facebook/detr-resnet-50",
         | 
| 155 | 
            -
                        device=device
         | 
| 156 | 
            -
                    )
         | 
| 157 | 
            -
                    
         | 
| 158 | 
            -
                    models['image_segmentation'] = pipeline(
         | 
| 159 | 
            -
                        "image-segmentation",
         | 
| 160 | 
            -
                        model="facebook/detr-resnet-50-panoptic",
         | 
| 161 | 
            -
                        device=device
         | 
| 162 | 
            -
                    )
         | 
| 163 | 
            -
                    
         | 
| 164 | 
            -
                    models['facial_recognition'] = pipeline(
         | 
| 165 | 
            -
                        "image-classification",
         | 
| 166 | 
            -
                        model="mo-thecreator/vit-Facial-Expression-Recognition",
         | 
| 167 | 
            -
                        device=device
         | 
| 168 | 
            -
                    )
         | 
| 169 | 
            -
                    
         | 
| 170 | 
            -
                    # Modelos de áudio
         | 
| 171 | 
            -
                    models['speech_to_text'] = pipeline(
         | 
| 172 | 
            -
                        "automatic-speech-recognition",
         | 
| 173 | 
            -
                        model="openai/whisper-base",
         | 
| 174 | 
            -
                        device=device
         | 
| 175 | 
            -
                    )
         | 
| 176 | 
            -
                    
         | 
| 177 | 
            -
                    models['audio_classification'] = pipeline(
         | 
| 178 | 
            -
                        "audio-classification",
         | 
| 179 | 
            -
                        model="superb/hubert-base-superb-er",
         | 
| 180 | 
            -
                        device=device
         | 
| 181 | 
            -
                    )
         | 
| 182 | 
            -
                    
         | 
| 183 | 
            -
                    # Modelos generativos
         | 
| 184 | 
            -
                    models['text_to_image'] = StableDiffusionPipeline.from_pretrained(
         | 
| 185 | 
            -
                        "runwayml/stable-diffusion-v1-5",
         | 
| 186 | 
            -
                        torch_dtype=torch.float16,
         | 
| 187 | 
            -
                        use_safetensors=True,
         | 
| 188 | 
            -
                        safety_checker=None,
         | 
| 189 | 
            -
                        variant="fp16"
         | 
| 190 | 
            -
                    )
         | 
| 191 | 
            -
                    
         | 
| 192 | 
             
                except Exception as e:
         | 
| 193 | 
            -
                    st.error(f"Erro  | 
| 194 | 
            -
                    logging. | 
| 195 | 
            -
                     | 
| 196 | 
            -
             | 
| 197 | 
            -
                return models
         | 
| 198 |  | 
| 199 | 
             
            def validate_audio_file(file: UploadedFile) -> bool:
         | 
| 200 | 
             
                """Valida o arquivo de áudio"""
         | 
| 201 | 
             
                valid_extensions = ['.wav', '.mp3', '.flac', '.m4a']
         | 
| 202 | 
            -
                 | 
| 203 | 
            -
                    return False
         | 
| 204 | 
            -
                return True
         | 
| 205 |  | 
| 206 | 
             
            def validate_image_file(file: UploadedFile) -> bool:
         | 
| 207 | 
             
                """Valida o arquivo de imagem"""
         | 
| @@ -223,11 +161,11 @@ def process_audio_file(audio_file): | |
| 223 |  | 
| 224 | 
             
                    audio_array, sample_rate = librosa.load(tmp_file_path, sr=16000)
         | 
| 225 | 
             
                    os.unlink(tmp_file_path)
         | 
| 226 | 
            -
                    
         | 
| 227 | 
             
                    return audio_array
         | 
| 228 | 
             
                except Exception as e:
         | 
| 229 | 
             
                    st.error(f"Erro ao processar áudio: {str(e)}")
         | 
| 230 | 
             
                    logging.error(f"Erro no processamento de áudio: {e}")
         | 
|  | |
| 231 | 
             
                    return None
         | 
| 232 |  | 
| 233 | 
             
            def process_image_file(image_file):
         | 
| @@ -240,6 +178,7 @@ def process_image_file(image_file): | |
| 240 | 
             
                except Exception as e:
         | 
| 241 | 
             
                    st.error(f"Erro ao processar imagem: {str(e)}")
         | 
| 242 | 
             
                    logging.error(f"Erro no processamento de imagem: {e}")
         | 
|  | |
| 243 | 
             
                    return None
         | 
| 244 |  | 
| 245 | 
             
            def display_results(result, model_key, input_text=None):
         | 
| @@ -304,6 +243,61 @@ def display_results(result, model_key, input_text=None): | |
| 304 | 
             
                    st.subheader("🎨 Imagem Gerada")
         | 
| 305 | 
             
                    st.image(result[0], caption="Imagem gerada a partir do texto")
         | 
| 306 |  | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 307 | 
             
            def get_use_cases():
         | 
| 308 | 
             
                """Retorna os casos de uso para cada modelo"""
         | 
| 309 | 
             
                return {
         | 
| @@ -315,6 +309,7 @@ def get_use_cases(): | |
| 315 | 
             
                        'demo_input': "A entrega foi super rápida, adorei!",
         | 
| 316 | 
             
                        'demo_type': 'text'
         | 
| 317 | 
             
                    },
         | 
|  | |
| 318 | 
             
                    'text_classification': {
         | 
| 319 | 
             
                        'title': "Classificação de Texto",
         | 
| 320 | 
             
                        'description': "Classifica e-mails recebidos como positivos ou negativos para priorizar respostas ou identificar reclamações.",
         | 
| @@ -432,13 +427,14 @@ def handle_use_case_demo(models, use_case_key, use_case): | |
| 432 |  | 
| 433 | 
             
                st.subheader("📊 Demonstração")
         | 
| 434 | 
             
                try:
         | 
|  | |
| 435 | 
             
                    if use_case['demo_type'] == 'text':
         | 
| 436 | 
             
                        with st.spinner("Processando demonstração..."):
         | 
| 437 | 
            -
                            result =  | 
| 438 | 
             
                            display_results(result, use_case_key, input_text=use_case['demo_input'])
         | 
| 439 | 
             
                    elif use_case['demo_type'] == 'qa':
         | 
| 440 | 
             
                        with st.spinner("Processando demonstração..."):
         | 
| 441 | 
            -
                            result =  | 
| 442 | 
             
                                question=use_case['demo_input']['question'],
         | 
| 443 | 
             
                                context=use_case['demo_input']['context']
         | 
| 444 | 
             
                            )
         | 
| @@ -450,6 +446,7 @@ def handle_use_case_demo(models, use_case_key, use_case): | |
| 450 | 
             
                except Exception as e:
         | 
| 451 | 
             
                    st.error(f"Erro ao executar demonstração: {str(e)}")
         | 
| 452 | 
             
                    logging.error(f"Erro na demonstração do caso de uso {use_case_key}: {e}")
         | 
|  | |
| 453 |  | 
| 454 | 
             
            def main():
         | 
| 455 | 
             
                # Inicializar banco de dados
         | 
| @@ -473,51 +470,62 @@ def main(): | |
| 473 | 
             
                name, authentication_status, username = authenticator.login('Login', 'main')
         | 
| 474 |  | 
| 475 | 
             
                if authentication_status:
         | 
| 476 | 
            -
                     | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 477 | 
             
                    authenticator.logout('Logout', 'sidebar')
         | 
| 478 | 
            -
             | 
| 479 | 
            -
                    st.title("🤖 Aplicação de IA Multi-Modal Avançada")
         | 
| 480 | 
            -
                    st.markdown("---")
         | 
| 481 |  | 
| 482 | 
            -
                    #  | 
| 483 | 
            -
                     | 
| 484 | 
            -
                         | 
|  | |
|  | |
|  | |
|  | |
| 485 |  | 
| 486 | 
            -
                     | 
| 487 | 
            -
             | 
| 488 | 
            -
             | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 489 |  | 
| 490 | 
             
                    # Abas para navegação
         | 
| 491 | 
             
                    tab1, tab2 = st.tabs(["Explorar Modelos", "Casos de Uso"])
         | 
| 492 |  | 
| 493 | 
             
                    with tab1:
         | 
| 494 | 
            -
                        # Sidebar para seleção de modelo
         | 
| 495 | 
             
                        st.sidebar.title("⚙️ Configurações")
         | 
| 496 | 
            -
                        model_categories = {
         | 
| 497 | 
            -
                            "📝 Processamento de Texto": [
         | 
| 498 | 
            -
                                ("Análise de Sentimento", "sentiment_analysis"),
         | 
| 499 | 
            -
                                ("Classificação de Texto", "text_classification"),
         | 
| 500 | 
            -
                                ("Resumo de Texto", "summarization"),
         | 
| 501 | 
            -
                                ("Perguntas e Respostas", "question_answering"),
         | 
| 502 | 
            -
                                ("Tradução (EN→PT)", "translation"),
         | 
| 503 | 
            -
                                ("Reconhecimento de Entidades", "ner"),
         | 
| 504 | 
            -
                                ("Geração de Texto", "text_generation")
         | 
| 505 | 
            -
                            ],
         | 
| 506 | 
            -
                            "🖼️ Processamento de Imagem": [
         | 
| 507 | 
            -
                                ("Classificação de Imagem", "image_classification"),
         | 
| 508 | 
            -
                                ("Detecção de Objetos", "object_detection"),
         | 
| 509 | 
            -
                                ("Segmentação de Imagem", "image_segmentation"),
         | 
| 510 | 
            -
                                ("Reconhecimento Facial", "facial_recognition")
         | 
| 511 | 
            -
                            ],
         | 
| 512 | 
            -
                            "🎵 Processamento de Áudio": [
         | 
| 513 | 
            -
                                ("Transcrição de Áudio", "speech_to_text"),
         | 
| 514 | 
            -
                                ("Classificação de Emoções", "audio_classification")
         | 
| 515 | 
            -
                            ],
         | 
| 516 | 
            -
                            "✨ Modelos Generativos": [
         | 
| 517 | 
            -
                                ("Texto para Imagem", "text_to_image")
         | 
| 518 | 
            -
                            ]
         | 
| 519 | 
            -
                        }
         | 
| 520 | 
            -
                        
         | 
| 521 | 
             
                        selected_category = st.sidebar.selectbox(
         | 
| 522 | 
             
                            "Categoria",
         | 
| 523 | 
             
                            list(model_categories.keys()),
         | 
| @@ -531,13 +539,17 @@ def main(): | |
| 531 | 
             
                            index=0
         | 
| 532 | 
             
                        )
         | 
| 533 |  | 
| 534 | 
            -
                        # Obter chave do modelo selecionado
         | 
| 535 | 
             
                        model_key = next(key for name, key in model_categories[selected_category] if name == selected_model)
         | 
| 536 |  | 
| 537 | 
            -
                        #  | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 538 | 
             
                        st.header(f"{selected_model}")
         | 
| 539 |  | 
| 540 | 
            -
                        # Accordion para informações do modelo
         | 
| 541 | 
             
                        with st.expander("ℹ️ Sobre este modelo"):
         | 
| 542 | 
             
                            model_info = {
         | 
| 543 | 
             
                                'sentiment_analysis': "Analisa o sentimento expresso em um texto (positivo/negativo/neutro).",
         | 
| @@ -557,7 +569,6 @@ def main(): | |
| 557 | 
             
                            }
         | 
| 558 | 
             
                            st.info(model_info.get(model_key, "Informações detalhadas sobre este modelo."))
         | 
| 559 |  | 
| 560 | 
            -
                        # Processamento baseado no tipo de modelo
         | 
| 561 | 
             
                        try:
         | 
| 562 | 
             
                            if model_key in ['sentiment_analysis', 'text_classification', 'summarization', 
         | 
| 563 | 
             
                                            'translation', 'text_generation', 'ner']:
         | 
| @@ -578,7 +589,8 @@ def main(): | |
| 578 |  | 
| 579 | 
             
                        except Exception as e:
         | 
| 580 | 
             
                            st.error(f"Erro inesperado durante a execução: {str(e)}")
         | 
| 581 | 
            -
                            logging. | 
|  | |
| 582 |  | 
| 583 | 
             
                    with tab2:
         | 
| 584 | 
             
                        st.header("Casos de Uso")
         | 
| @@ -612,7 +624,6 @@ def handle_text_models(models, model_key, model_name): | |
| 612 | 
             
                    key=f"text_input_{model_key}"
         | 
| 613 | 
             
                )
         | 
| 614 |  | 
| 615 | 
            -
                # Parâmetros adicionais para alguns modelos
         | 
| 616 | 
             
                advanced_params = {}
         | 
| 617 | 
             
                if model_key == 'summarization':
         | 
| 618 | 
             
                    with st.expander("⚙️ Parâmetros Avançados"):
         | 
| @@ -629,10 +640,11 @@ def handle_text_models(models, model_key, model_name): | |
| 629 | 
             
                    if input_text.strip():
         | 
| 630 | 
             
                        with st.spinner("Processando..."):
         | 
| 631 | 
             
                            try:
         | 
|  | |
| 632 | 
             
                                if model_key == 'ner':
         | 
| 633 | 
            -
                                    result =  | 
| 634 | 
             
                                elif model_key == 'text_generation':
         | 
| 635 | 
            -
                                    result =  | 
| 636 | 
             
                                        input_text,
         | 
| 637 | 
             
                                        max_new_tokens=advanced_params.get('max_length', 100),
         | 
| 638 | 
             
                                        do_sample=True,
         | 
| @@ -642,13 +654,14 @@ def handle_text_models(models, model_key, model_name): | |
| 642 | 
             
                                        num_return_sequences=advanced_params.get('num_return_sequences', 1)
         | 
| 643 | 
             
                                    )
         | 
| 644 | 
             
                                else:
         | 
| 645 | 
            -
                                    result =  | 
| 646 |  | 
| 647 | 
             
                                display_results(result, model_key, input_text=input_text)
         | 
| 648 |  | 
| 649 | 
             
                            except Exception as e:
         | 
| 650 | 
             
                                st.error(f"Erro ao processar texto: {str(e)}")
         | 
| 651 | 
             
                                logging.error(f"Erro no modelo {model_key}: {e}")
         | 
|  | |
| 652 | 
             
                    else:
         | 
| 653 | 
             
                        st.warning("⚠️ Por favor, insira um texto válido.")
         | 
| 654 |  | 
| @@ -679,7 +692,8 @@ def handle_qa_model(models, model_key): | |
| 679 | 
             
                    if context.strip() and question.strip():
         | 
| 680 | 
             
                        with st.spinner("Buscando resposta..."):
         | 
| 681 | 
             
                            try:
         | 
| 682 | 
            -
                                 | 
|  | |
| 683 |  | 
| 684 | 
             
                                if result['score'] < confidence_threshold:
         | 
| 685 | 
             
                                    st.warning(f"⚠️ Confiança baixa na resposta ({result['score']:.2%})")
         | 
| @@ -693,6 +707,7 @@ def handle_qa_model(models, model_key): | |
| 693 | 
             
                            except Exception as e:
         | 
| 694 | 
             
                                st.error(f"Erro ao processar Q&A: {str(e)}")
         | 
| 695 | 
             
                                logging.error(f"Erro no modelo Q&A: {e}")
         | 
|  | |
| 696 | 
             
                    else:
         | 
| 697 | 
             
                        st.warning("⚠️ Por favor, forneça tanto o contexto quanto a pergunta.")
         | 
| 698 |  | 
| @@ -724,12 +739,13 @@ def handle_image_models(models, model_key, model_name): | |
| 724 | 
             
                            if image:
         | 
| 725 | 
             
                                with st.spinner("Analisando imagem..."):
         | 
| 726 | 
             
                                    try:
         | 
| 727 | 
            -
                                         | 
|  | |
| 728 | 
             
                                        display_results(result, model_key)
         | 
| 729 | 
            -
                                            
         | 
| 730 | 
             
                                    except Exception as e:
         | 
| 731 | 
             
                                        st.error(f"Erro ao processar imagem: {str(e)}")
         | 
| 732 | 
             
                                        logging.error(f"Erro no modelo {model_key}: {e}")
         | 
|  | |
| 733 |  | 
| 734 | 
             
            def handle_audio_models(models, model_key):
         | 
| 735 | 
             
                """Manipula modelos de áudio"""
         | 
| @@ -753,16 +769,16 @@ def handle_audio_models(models, model_key): | |
| 753 | 
             
                        with st.spinner("Processando áudio..."):
         | 
| 754 | 
             
                            try:
         | 
| 755 | 
             
                                audio_array = process_audio_file(uploaded_file)
         | 
| 756 | 
            -
                                
         | 
| 757 | 
             
                                if audio_array is not None:
         | 
| 758 | 
            -
                                     | 
|  | |
| 759 | 
             
                                    display_results(result, model_key)
         | 
| 760 | 
             
                                else:
         | 
| 761 | 
             
                                    st.error("Não foi possível processar o arquivo de áudio.")
         | 
| 762 | 
            -
                                    
         | 
| 763 | 
             
                            except Exception as e:
         | 
| 764 | 
             
                                st.error(f"Erro ao processar áudio: {str(e)}")
         | 
| 765 | 
             
                                logging.error(f"Erro no modelo {model_key}: {e}")
         | 
|  | |
| 766 |  | 
| 767 | 
             
            def handle_generative_models(models, model_key):
         | 
| 768 | 
             
                """Manipula modelos generativos"""
         | 
| @@ -786,7 +802,8 @@ def handle_generative_models(models, model_key): | |
| 786 | 
             
                    if prompt.strip():
         | 
| 787 | 
             
                        with st.spinner("Criando imagem..."):
         | 
| 788 | 
             
                            try:
         | 
| 789 | 
            -
                                 | 
|  | |
| 790 | 
             
                                    prompt,
         | 
| 791 | 
             
                                    height=height,
         | 
| 792 | 
             
                                    width=width,
         | 
| @@ -794,10 +811,10 @@ def handle_generative_models(models, model_key): | |
| 794 | 
             
                                    guidance_scale=guidance_scale
         | 
| 795 | 
             
                                )
         | 
| 796 | 
             
                                display_results(result, model_key)
         | 
| 797 | 
            -
                                
         | 
| 798 | 
             
                            except Exception as e:
         | 
| 799 | 
             
                                st.error(f"Erro ao gerar imagem: {str(e)}")
         | 
| 800 | 
             
                                logging.error(f"Erro no modelo text-to-image: {e}")
         | 
|  | |
| 801 | 
             
                    else:
         | 
| 802 | 
             
                        st.warning("⚠️ Por favor, insira uma descrição para a imagem.")
         | 
| 803 |  | 
|  | |
| 2 | 
             
            import streamlit_authenticator as stauth
         | 
| 3 | 
             
            import sqlite3
         | 
| 4 | 
             
            import os
         | 
| 5 | 
            +
            import psycopg2
         | 
| 6 | 
            +
            import jwt
         | 
| 7 | 
            +
            from datetime import datetime, timedelta
         | 
| 8 | 
             
            from transformers import pipeline, AutoModelForCausalLM, AutoTokenizer
         | 
| 9 | 
             
            import torch
         | 
| 10 | 
             
            from PIL import Image
         | 
|  | |
| 15 | 
             
            import tempfile
         | 
| 16 | 
             
            from streamlit.runtime.uploaded_file_manager import UploadedFile
         | 
| 17 | 
             
            from diffusers import StableDiffusionPipeline
         | 
| 18 | 
            +
            import sentry_sdk
         | 
| 19 | 
            +
            from streamlit_tour import st_tour
         | 
| 20 |  | 
| 21 | 
             
            # Configurar página
         | 
| 22 | 
             
            st.set_page_config(
         | 
|  | |
| 25 | 
             
                layout="wide"
         | 
| 26 | 
             
            )
         | 
| 27 |  | 
| 28 | 
            +
            # Configurar logging e Sentry
         | 
| 29 | 
            +
            sentry_sdk.init(os.getenv('SENTRY_DSN', ''), traces_sample_rate=1.0)
         | 
| 30 | 
             
            logging.basicConfig(
         | 
| 31 | 
            +
                filename='/home/user/app/private/app_errors.log',
         | 
| 32 | 
             
                level=logging.ERROR,
         | 
| 33 | 
             
                format='%(asctime)s - %(levelname)s - %(message)s'
         | 
| 34 | 
             
            )
         | 
| 35 |  | 
| 36 | 
            +
            # Configurar banco de dados
         | 
| 37 | 
             
            def init_db():
         | 
| 38 | 
             
                """Inicializa o banco de dados SQLite com tabela de usuários"""
         | 
| 39 | 
            +
                db_path = os.getenv('DB_PATH', '/home/user/app/private/users.db')
         | 
| 40 | 
            +
                os.makedirs(os.path.dirname(db_path), exist_ok=True)
         | 
| 41 | 
             
                conn = sqlite3.connect(db_path)
         | 
| 42 | 
             
                cursor = conn.cursor()
         | 
| 43 |  | 
|  | |
| 44 | 
             
                cursor.execute('''
         | 
| 45 | 
             
                    CREATE TABLE IF NOT EXISTS users (
         | 
| 46 | 
             
                        username TEXT PRIMARY KEY,
         | 
| 47 | 
             
                        name TEXT NOT NULL,
         | 
| 48 | 
            +
                        password TEXT NOT NULL,
         | 
| 49 | 
            +
                        role TEXT NOT NULL DEFAULT 'user'
         | 
| 50 | 
             
                    )
         | 
| 51 | 
             
                ''')
         | 
| 52 |  | 
| 53 | 
            +
                # Adicionar admin padrão (remover em produção)
         | 
| 54 | 
             
                try:
         | 
| 55 | 
            +
                    hashed_password = stauth.Hasher(['admin123']).generate()[0]
         | 
| 56 | 
             
                    cursor.execute('''
         | 
| 57 | 
            +
                        INSERT OR IGNORE INTO users (username, name, password, role)
         | 
| 58 | 
            +
                        VALUES (?, ?, ?, ?)
         | 
| 59 | 
            +
                    ''', ('admin', 'Administrador', hashed_password, 'admin'))
         | 
|  | |
|  | |
|  | |
|  | |
| 60 | 
             
                    conn.commit()
         | 
| 61 | 
             
                except Exception as e:
         | 
| 62 | 
             
                    logging.error(f"Erro ao inicializar banco de dados: {e}")
         | 
| 63 | 
            +
                    sentry_sdk.capture_exception(e)
         | 
| 64 | 
             
                    st.error(f"Erro ao inicializar banco de dados: {str(e)}")
         | 
| 65 |  | 
| 66 | 
             
                conn.close()
         | 
|  | |
| 68 | 
             
            def load_users_from_db():
         | 
| 69 | 
             
                """Carrega usuários do banco de dados SQLite"""
         | 
| 70 | 
             
                try:
         | 
| 71 | 
            +
                    db_path = os.getenv('DB_PATH', '/home/user/app/private/users.db')
         | 
| 72 | 
             
                    conn = sqlite3.connect(db_path)
         | 
| 73 | 
             
                    cursor = conn.cursor()
         | 
| 74 | 
            +
                    cursor.execute("SELECT username, name, password, role FROM users")
         | 
| 75 | 
            +
                    users = {row[0]: {'name': row[1], 'password': row[2], 'role': row[3]} for row in cursor.fetchall()}
         | 
| 76 | 
             
                    conn.close()
         | 
| 77 |  | 
| 78 | 
             
                    config = {
         | 
|  | |
| 82 | 
             
                    }
         | 
| 83 | 
             
                    return config
         | 
| 84 | 
             
                except Exception as e:
         | 
| 85 | 
            +
                    st.error(f"Erro ao carregar usuários: {str(e)}")
         | 
| 86 | 
             
                    logging.error(f"Erro ao carregar usuários: {e}")
         | 
| 87 | 
            +
                    sentry_sdk.capture_exception(e)
         | 
| 88 | 
             
                    return None
         | 
| 89 |  | 
| 90 | 
            +
            # Cache para modelos
         | 
| 91 | 
             
            @st.cache_resource(show_spinner=False)
         | 
| 92 | 
            +
            def load_model(model_key):
         | 
| 93 | 
            +
                """Carrega modelo específico com cache persistente"""
         | 
| 94 | 
            +
                device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
         | 
| 95 | 
            +
                cache_dir = "/home/user/app/model_cache"
         | 
| 96 | 
            +
                os.makedirs(cache_dir, exist_ok=True)
         | 
| 97 | 
            +
                logging.info(f"Carregando modelo {model_key} em {device} com cache em {cache_dir}")
         | 
| 98 |  | 
| 99 | 
             
                try:
         | 
| 100 | 
            +
                    if model_key == 'sentiment_analysis':
         | 
| 101 | 
            +
                        return pipeline("sentiment-analysis", model="cardiffnlp/twitter-roberta-base-sentiment-latest", device=device, cache_dir=cache_dir)
         | 
| 102 | 
            +
                    elif model_key == 'text_classification':
         | 
| 103 | 
            +
                        return pipeline("text-classification", model="distilbert-base-uncased-finetuned-sst-2-english", device=device, cache_dir=cache_dir)
         | 
| 104 | 
            +
                    elif model_key == 'summarization':
         | 
| 105 | 
            +
                        return pipeline("summarization", model="facebook/bart-large-cnn", device=device, max_length=150, min_length=30, cache_dir=cache_dir)
         | 
| 106 | 
            +
                    elif model_key == 'question_answering':
         | 
| 107 | 
            +
                        return pipeline("question-answering", model="deepset/roberta-base-squad2", device=device, cache_dir=cache_dir)
         | 
| 108 | 
            +
                    elif model_key == 'translation':
         | 
| 109 | 
            +
                        return pipeline("translation", model="Helsinki-NLP/opus-mt-tc-big-en-pt", device=device, cache_dir=cache_dir)
         | 
| 110 | 
            +
                    elif model_key == 'text_generation':
         | 
| 111 | 
            +
                        tokenizer = AutoTokenizer.from_pretrained("gpt2", cache_dir=cache_dir)
         | 
| 112 | 
            +
                        model = AutoModelForCausalLM.from_pretrained("gpt2", cache_dir=cache_dir)
         | 
| 113 | 
            +
                        model.config.pad_token_id = model.config.eos_token_id
         | 
| 114 | 
            +
                        return pipeline("text-generation", model=model, tokenizer=tokenizer, device=device)
         | 
| 115 | 
            +
                    elif model_key == 'ner':
         | 
| 116 | 
            +
                        return pipeline("ner", model="dbmdz/bert-large-cased-finetuned-conll03-english", device=device, aggregation_strategy="simple", cache_dir=cache_dir)
         | 
| 117 | 
            +
                    elif model_key == 'image_classification':
         | 
| 118 | 
            +
                        return pipeline("image-classification", model="google/vit-base-patch16-224", device=device, cache_dir=cache_dir)
         | 
| 119 | 
            +
                    elif model_key == 'object_detection':
         | 
| 120 | 
            +
                        return pipeline("object-detection", model="facebook/detr-resnet-50", device=device, cache_dir=cache_dir)
         | 
| 121 | 
            +
                    elif model_key == 'image_segmentation':
         | 
| 122 | 
            +
                        return pipeline("image-segmentation", model="facebook/detr-resnet-50-panoptic", device=device, cache_dir=cache_dir)
         | 
| 123 | 
            +
                    elif model_key == 'facial_recognition':
         | 
| 124 | 
            +
                        return pipeline("image-classification", model="mo-thecreator/vit-Facial-Expression-Recognition", device=device, cache_dir=cache_dir)
         | 
| 125 | 
            +
                    elif model_key == 'speech_to_text':
         | 
| 126 | 
            +
                        return pipeline("automatic-speech-recognition", model="openai/whisper-base", device=device, cache_dir=cache_dir)
         | 
| 127 | 
            +
                    elif model_key == 'audio_classification':
         | 
| 128 | 
            +
                        return pipeline("audio-classification", model="superb/hubert-base-superb-er", device=device, cache_dir=cache_dir)
         | 
| 129 | 
            +
                    elif model_key == 'text_to_image':
         | 
| 130 | 
            +
                        return StableDiffusionPipeline.from_pretrained(
         | 
| 131 | 
            +
                            "runwayml/stable-diffusion-v1-5", torch_dtype=torch.float16, use_safetensors=True, safety_checker=None, variant="fp16", cache_dir=cache_dir
         | 
| 132 | 
            +
                        )
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 133 | 
             
                except Exception as e:
         | 
| 134 | 
            +
                    st.error(f"Erro ao carregar modelo {model_key}: {str(e)}")
         | 
| 135 | 
            +
                    logging.error(f"Erro ao carregar modelo {model_key}: {e}")
         | 
| 136 | 
            +
                    sentry_sdk.capture_exception(e)
         | 
| 137 | 
            +
                    return None
         | 
|  | |
| 138 |  | 
| 139 | 
             
            def validate_audio_file(file: UploadedFile) -> bool:
         | 
| 140 | 
             
                """Valida o arquivo de áudio"""
         | 
| 141 | 
             
                valid_extensions = ['.wav', '.mp3', '.flac', '.m4a']
         | 
| 142 | 
            +
                return any(file.name.lower().endswith(ext) for ext in valid_extensions)
         | 
|  | |
|  | |
| 143 |  | 
| 144 | 
             
            def validate_image_file(file: UploadedFile) -> bool:
         | 
| 145 | 
             
                """Valida o arquivo de imagem"""
         | 
|  | |
| 161 |  | 
| 162 | 
             
                    audio_array, sample_rate = librosa.load(tmp_file_path, sr=16000)
         | 
| 163 | 
             
                    os.unlink(tmp_file_path)
         | 
|  | |
| 164 | 
             
                    return audio_array
         | 
| 165 | 
             
                except Exception as e:
         | 
| 166 | 
             
                    st.error(f"Erro ao processar áudio: {str(e)}")
         | 
| 167 | 
             
                    logging.error(f"Erro no processamento de áudio: {e}")
         | 
| 168 | 
            +
                    sentry_sdk.capture_exception(e)
         | 
| 169 | 
             
                    return None
         | 
| 170 |  | 
| 171 | 
             
            def process_image_file(image_file):
         | 
|  | |
| 178 | 
             
                except Exception as e:
         | 
| 179 | 
             
                    st.error(f"Erro ao processar imagem: {str(e)}")
         | 
| 180 | 
             
                    logging.error(f"Erro no processamento de imagem: {e}")
         | 
| 181 | 
            +
                    sentry_sdk.capture_exception(e)
         | 
| 182 | 
             
                    return None
         | 
| 183 |  | 
| 184 | 
             
            def display_results(result, model_key, input_text=None):
         | 
|  | |
| 243 | 
             
                    st.subheader("🎨 Imagem Gerada")
         | 
| 244 | 
             
                    st.image(result[0], caption="Imagem gerada a partir do texto")
         | 
| 245 |  | 
| 246 | 
            +
            def load_branding(username):
         | 
| 247 | 
            +
                """Carrega branding personalizado por usuário"""
         | 
| 248 | 
            +
                branding = {
         | 
| 249 | 
            +
                    'admin': {'logo': '/home/user/app/logos/admin_logo.png', 'title': 'Bem-vindo, Administrador!'},
         | 
| 250 | 
            +
                    'cliente': {'logo': '/home/user/app/logos/cliente_logo.png', 'title': 'Bem-vindo, Cliente!'},
         | 
| 251 | 
            +
                    'empresa1': {'logo': '/home/user/app/logos/empresa1_logo.png', 'title': 'Bem-vindo, Empresa Um!'}
         | 
| 252 | 
            +
                }
         | 
| 253 | 
            +
                return branding.get(username, {'logo': None, 'title': 'Bem-vindo!'})
         | 
| 254 | 
            +
             | 
| 255 | 
            +
            def admin_panel(authenticator):
         | 
| 256 | 
            +
                """Painel administrativo para gerenciar usuários"""
         | 
| 257 | 
            +
                if st.session_state.get('role') == 'admin':
         | 
| 258 | 
            +
                    st.sidebar.subheader("Painel Admin")
         | 
| 259 | 
            +
                    with st.sidebar.form("add_user_form"):
         | 
| 260 | 
            +
                        username = st.text_input("Username")
         | 
| 261 | 
            +
                        name = st.text_input("Nome")
         | 
| 262 | 
            +
                        password = st.text_input("Senha", type="password")
         | 
| 263 | 
            +
                        role = st.selectbox("Role", ["user", "admin"])
         | 
| 264 | 
            +
                        if st.form_submit_button("Adicionar Usuário"):
         | 
| 265 | 
            +
                            hashed_password = stauth.Hasher([password]).generate()[0]
         | 
| 266 | 
            +
                            db_path = os.getenv('DB_PATH', '/home/user/app/private/users.db')
         | 
| 267 | 
            +
                            conn = sqlite3.connect(db_path)
         | 
| 268 | 
            +
                            cursor = conn.cursor()
         | 
| 269 | 
            +
                            try:
         | 
| 270 | 
            +
                                cursor.execute('INSERT INTO users (username, name, password, role) VALUES (?, ?, ?, ?)', 
         | 
| 271 | 
            +
                                             (username, name, hashed_password, role))
         | 
| 272 | 
            +
                                conn.commit()
         | 
| 273 | 
            +
                                st.success(f"Usuário {username} adicionado!")
         | 
| 274 | 
            +
                            except sqlite3.IntegrityError:
         | 
| 275 | 
            +
                                st.error("Usuário já existe.")
         | 
| 276 | 
            +
                            except Exception as e:
         | 
| 277 | 
            +
                                st.error(f"Erro ao adicionar usuário: {str(e)}")
         | 
| 278 | 
            +
                                logging.error(f"Erro ao adicionar usuário: {e}")
         | 
| 279 | 
            +
                                sentry_sdk.capture_exception(e)
         | 
| 280 | 
            +
                            conn.close()
         | 
| 281 | 
            +
                    
         | 
| 282 | 
            +
                    with st.sidebar.form("remove_user_form"):
         | 
| 283 | 
            +
                        username_to_remove = st.text_input("Username para Remover")
         | 
| 284 | 
            +
                        if st.form_submit_button("Remover Usuário"):
         | 
| 285 | 
            +
                            db_path = os.getenv('DB_PATH', '/home/user/app/private/users.db')
         | 
| 286 | 
            +
                            conn = sqlite3.connect(db_path)
         | 
| 287 | 
            +
                            cursor = conn.cursor()
         | 
| 288 | 
            +
                            try:
         | 
| 289 | 
            +
                                cursor.execute('DELETE FROM users WHERE username = ?', (username_to_remove,))
         | 
| 290 | 
            +
                                conn.commit()
         | 
| 291 | 
            +
                                if cursor.rowcount > 0:
         | 
| 292 | 
            +
                                    st.success(f"Usuário {username_to_remove} removido!")
         | 
| 293 | 
            +
                                else:
         | 
| 294 | 
            +
                                    st.error("Usuário não encontrado.")
         | 
| 295 | 
            +
                            except Exception as e:
         | 
| 296 | 
            +
                                st.error(f"Erro ao remover usuário: {str(e)}")
         | 
| 297 | 
            +
                                logging.error(f"Erro ao remover usuário: {e}")
         | 
| 298 | 
            +
                                sentry_sdk.capture_exception(e)
         | 
| 299 | 
            +
                            conn.close()
         | 
| 300 | 
            +
             | 
| 301 | 
             
            def get_use_cases():
         | 
| 302 | 
             
                """Retorna os casos de uso para cada modelo"""
         | 
| 303 | 
             
                return {
         | 
|  | |
| 309 | 
             
                        'demo_input': "A entrega foi super rápida, adorei!",
         | 
| 310 | 
             
                        'demo_type': 'text'
         | 
| 311 | 
             
                    },
         | 
| 312 | 
            +
                    # Outros casos de uso mantidos idênticos ao original
         | 
| 313 | 
             
                    'text_classification': {
         | 
| 314 | 
             
                        'title': "Classificação de Texto",
         | 
| 315 | 
             
                        'description': "Classifica e-mails recebidos como positivos ou negativos para priorizar respostas ou identificar reclamações.",
         | 
|  | |
| 427 |  | 
| 428 | 
             
                st.subheader("📊 Demonstração")
         | 
| 429 | 
             
                try:
         | 
| 430 | 
            +
                    model = models.get(use_case_key) or load_model(use_case_key)
         | 
| 431 | 
             
                    if use_case['demo_type'] == 'text':
         | 
| 432 | 
             
                        with st.spinner("Processando demonstração..."):
         | 
| 433 | 
            +
                            result = model(use_case['demo_input'])
         | 
| 434 | 
             
                            display_results(result, use_case_key, input_text=use_case['demo_input'])
         | 
| 435 | 
             
                    elif use_case['demo_type'] == 'qa':
         | 
| 436 | 
             
                        with st.spinner("Processando demonstração..."):
         | 
| 437 | 
            +
                            result = model(
         | 
| 438 | 
             
                                question=use_case['demo_input']['question'],
         | 
| 439 | 
             
                                context=use_case['demo_input']['context']
         | 
| 440 | 
             
                            )
         | 
|  | |
| 446 | 
             
                except Exception as e:
         | 
| 447 | 
             
                    st.error(f"Erro ao executar demonstração: {str(e)}")
         | 
| 448 | 
             
                    logging.error(f"Erro na demonstração do caso de uso {use_case_key}: {e}")
         | 
| 449 | 
            +
                    sentry_sdk.capture_exception(e)
         | 
| 450 |  | 
| 451 | 
             
            def main():
         | 
| 452 | 
             
                # Inicializar banco de dados
         | 
|  | |
| 470 | 
             
                name, authentication_status, username = authenticator.login('Login', 'main')
         | 
| 471 |  | 
| 472 | 
             
                if authentication_status:
         | 
| 473 | 
            +
                    # Gerenciar sessão
         | 
| 474 | 
            +
                    if "user_id" not in st.session_state:
         | 
| 475 | 
            +
                        st.session_state.user_id = username
         | 
| 476 | 
            +
                        st.session_state.role = config['credentials']['usernames'][username]['role']
         | 
| 477 | 
            +
                    
         | 
| 478 | 
            +
                    # Carregar branding
         | 
| 479 | 
            +
                    branding = load_branding(username)
         | 
| 480 | 
            +
                    if branding['logo'] and os.path.exists(branding['logo']):
         | 
| 481 | 
            +
                        st.image(branding['logo'], width=150)
         | 
| 482 | 
            +
                    st.title(branding['title'])
         | 
| 483 | 
            +
                    
         | 
| 484 | 
             
                    authenticator.logout('Logout', 'sidebar')
         | 
| 485 | 
            +
                    admin_panel(authenticator)
         | 
|  | |
|  | |
| 486 |  | 
| 487 | 
            +
                    # Tour guiado
         | 
| 488 | 
            +
                    if st.sidebar.button("Iniciar Tour"):
         | 
| 489 | 
            +
                        st_tour([
         | 
| 490 | 
            +
                            {"element": "#login", "title": "Login", "description": "Faça login com suas credenciais."},
         | 
| 491 | 
            +
                            {"element": "#tab1", "title": "Explorar Modelos", "description": "Teste modelos de IA."},
         | 
| 492 | 
            +
                            {"element": "#tab2", "title": "Casos de Uso", "description": "Explore aplicações práticas."}
         | 
| 493 | 
            +
                        ])
         | 
| 494 |  | 
| 495 | 
            +
                    st.markdown("---")
         | 
| 496 | 
            +
                    
         | 
| 497 | 
            +
                    # Carregar modelos sob demanda
         | 
| 498 | 
            +
                    models = {}
         | 
| 499 | 
            +
                    model_categories = {
         | 
| 500 | 
            +
                        "📝 Processamento de Texto": [
         | 
| 501 | 
            +
                            ("Análise de Sentimento", "sentiment_analysis"),
         | 
| 502 | 
            +
                            ("Classificação de Texto", "text_classification"),
         | 
| 503 | 
            +
                            ("Resumo de Texto", "summarization"),
         | 
| 504 | 
            +
                            ("Perguntas e Respostas", "question_answering"),
         | 
| 505 | 
            +
                            ("Tradução (EN→PT)", "translation"),
         | 
| 506 | 
            +
                            ("Reconhecimento de Entidades", "ner"),
         | 
| 507 | 
            +
                            ("Geração de Texto", "text_generation")
         | 
| 508 | 
            +
                        ],
         | 
| 509 | 
            +
                        "🖼️ Processamento de Imagem": [
         | 
| 510 | 
            +
                            ("Classificação de Imagem", "image_classification"),
         | 
| 511 | 
            +
                            ("Detecção de Objetos", "object_detection"),
         | 
| 512 | 
            +
                            ("Segmentação de Imagem", "image_segmentation"),
         | 
| 513 | 
            +
                            ("Reconhecimento Facial", "facial_recognition")
         | 
| 514 | 
            +
                        ],
         | 
| 515 | 
            +
                        "🎵 Processamento de Áudio": [
         | 
| 516 | 
            +
                            ("Transcrição de Áudio", "speech_to_text"),
         | 
| 517 | 
            +
                            ("Classificação de Emoções", "audio_classification")
         | 
| 518 | 
            +
                        ],
         | 
| 519 | 
            +
                        "✨ Modelos Generativos": [
         | 
| 520 | 
            +
                            ("Texto para Imagem", "text_to_image")
         | 
| 521 | 
            +
                        ]
         | 
| 522 | 
            +
                    }
         | 
| 523 |  | 
| 524 | 
             
                    # Abas para navegação
         | 
| 525 | 
             
                    tab1, tab2 = st.tabs(["Explorar Modelos", "Casos de Uso"])
         | 
| 526 |  | 
| 527 | 
             
                    with tab1:
         | 
|  | |
| 528 | 
             
                        st.sidebar.title("⚙️ Configurações")
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 529 | 
             
                        selected_category = st.sidebar.selectbox(
         | 
| 530 | 
             
                            "Categoria",
         | 
| 531 | 
             
                            list(model_categories.keys()),
         | 
|  | |
| 539 | 
             
                            index=0
         | 
| 540 | 
             
                        )
         | 
| 541 |  | 
|  | |
| 542 | 
             
                        model_key = next(key for name, key in model_categories[selected_category] if name == selected_model)
         | 
| 543 |  | 
| 544 | 
            +
                        # Carregar modelo com barra de progresso
         | 
| 545 | 
            +
                        if model_key not in models:
         | 
| 546 | 
            +
                            with st.spinner(f"Carregando modelo {selected_model}..."):
         | 
| 547 | 
            +
                                progress = st.progress(0)
         | 
| 548 | 
            +
                                models[model_key] = load_model(model_key)
         | 
| 549 | 
            +
                                progress.progress(100)
         | 
| 550 | 
            +
                        
         | 
| 551 | 
             
                        st.header(f"{selected_model}")
         | 
| 552 |  | 
|  | |
| 553 | 
             
                        with st.expander("ℹ️ Sobre este modelo"):
         | 
| 554 | 
             
                            model_info = {
         | 
| 555 | 
             
                                'sentiment_analysis': "Analisa o sentimento expresso em um texto (positivo/negativo/neutro).",
         | 
|  | |
| 569 | 
             
                            }
         | 
| 570 | 
             
                            st.info(model_info.get(model_key, "Informações detalhadas sobre este modelo."))
         | 
| 571 |  | 
|  | |
| 572 | 
             
                        try:
         | 
| 573 | 
             
                            if model_key in ['sentiment_analysis', 'text_classification', 'summarization', 
         | 
| 574 | 
             
                                            'translation', 'text_generation', 'ner']:
         | 
|  | |
| 589 |  | 
| 590 | 
             
                        except Exception as e:
         | 
| 591 | 
             
                            st.error(f"Erro inesperado durante a execução: {str(e)}")
         | 
| 592 | 
            +
                            logging.error(f"Erro durante a execução do modelo {model_key}: {e}")
         | 
| 593 | 
            +
                            sentry_sdk.capture_exception(e)
         | 
| 594 |  | 
| 595 | 
             
                    with tab2:
         | 
| 596 | 
             
                        st.header("Casos de Uso")
         | 
|  | |
| 624 | 
             
                    key=f"text_input_{model_key}"
         | 
| 625 | 
             
                )
         | 
| 626 |  | 
|  | |
| 627 | 
             
                advanced_params = {}
         | 
| 628 | 
             
                if model_key == 'summarization':
         | 
| 629 | 
             
                    with st.expander("⚙️ Parâmetros Avançados"):
         | 
|  | |
| 640 | 
             
                    if input_text.strip():
         | 
| 641 | 
             
                        with st.spinner("Processando..."):
         | 
| 642 | 
             
                            try:
         | 
| 643 | 
            +
                                model = models.get(model_key) or load_model(model_key)
         | 
| 644 | 
             
                                if model_key == 'ner':
         | 
| 645 | 
            +
                                    result = model(input_text)
         | 
| 646 | 
             
                                elif model_key == 'text_generation':
         | 
| 647 | 
            +
                                    result = model(
         | 
| 648 | 
             
                                        input_text,
         | 
| 649 | 
             
                                        max_new_tokens=advanced_params.get('max_length', 100),
         | 
| 650 | 
             
                                        do_sample=True,
         | 
|  | |
| 654 | 
             
                                        num_return_sequences=advanced_params.get('num_return_sequences', 1)
         | 
| 655 | 
             
                                    )
         | 
| 656 | 
             
                                else:
         | 
| 657 | 
            +
                                    result = model(input_text, **advanced_params)
         | 
| 658 |  | 
| 659 | 
             
                                display_results(result, model_key, input_text=input_text)
         | 
| 660 |  | 
| 661 | 
             
                            except Exception as e:
         | 
| 662 | 
             
                                st.error(f"Erro ao processar texto: {str(e)}")
         | 
| 663 | 
             
                                logging.error(f"Erro no modelo {model_key}: {e}")
         | 
| 664 | 
            +
                                sentry_sdk.capture_exception(e)
         | 
| 665 | 
             
                    else:
         | 
| 666 | 
             
                        st.warning("⚠️ Por favor, insira um texto válido.")
         | 
| 667 |  | 
|  | |
| 692 | 
             
                    if context.strip() and question.strip():
         | 
| 693 | 
             
                        with st.spinner("Buscando resposta..."):
         | 
| 694 | 
             
                            try:
         | 
| 695 | 
            +
                                model = models.get(model_key) or load_model(model_key)
         | 
| 696 | 
            +
                                result = model(question=question, context=context)
         | 
| 697 |  | 
| 698 | 
             
                                if result['score'] < confidence_threshold:
         | 
| 699 | 
             
                                    st.warning(f"⚠️ Confiança baixa na resposta ({result['score']:.2%})")
         | 
|  | |
| 707 | 
             
                            except Exception as e:
         | 
| 708 | 
             
                                st.error(f"Erro ao processar Q&A: {str(e)}")
         | 
| 709 | 
             
                                logging.error(f"Erro no modelo Q&A: {e}")
         | 
| 710 | 
            +
                                sentry_sdk.capture_exception(e)
         | 
| 711 | 
             
                    else:
         | 
| 712 | 
             
                        st.warning("⚠️ Por favor, forneça tanto o contexto quanto a pergunta.")
         | 
| 713 |  | 
|  | |
| 739 | 
             
                            if image:
         | 
| 740 | 
             
                                with st.spinner("Analisando imagem..."):
         | 
| 741 | 
             
                                    try:
         | 
| 742 | 
            +
                                        model = models.get(model_key) or load_model(model_key)
         | 
| 743 | 
            +
                                        result = model(image)
         | 
| 744 | 
             
                                        display_results(result, model_key)
         | 
|  | |
| 745 | 
             
                                    except Exception as e:
         | 
| 746 | 
             
                                        st.error(f"Erro ao processar imagem: {str(e)}")
         | 
| 747 | 
             
                                        logging.error(f"Erro no modelo {model_key}: {e}")
         | 
| 748 | 
            +
                                        sentry_sdk.capture_exception(e)
         | 
| 749 |  | 
| 750 | 
             
            def handle_audio_models(models, model_key):
         | 
| 751 | 
             
                """Manipula modelos de áudio"""
         | 
|  | |
| 769 | 
             
                        with st.spinner("Processando áudio..."):
         | 
| 770 | 
             
                            try:
         | 
| 771 | 
             
                                audio_array = process_audio_file(uploaded_file)
         | 
|  | |
| 772 | 
             
                                if audio_array is not None:
         | 
| 773 | 
            +
                                    model = models.get(model_key) or load_model(model_key)
         | 
| 774 | 
            +
                                    result = model(audio_array)
         | 
| 775 | 
             
                                    display_results(result, model_key)
         | 
| 776 | 
             
                                else:
         | 
| 777 | 
             
                                    st.error("Não foi possível processar o arquivo de áudio.")
         | 
|  | |
| 778 | 
             
                            except Exception as e:
         | 
| 779 | 
             
                                st.error(f"Erro ao processar áudio: {str(e)}")
         | 
| 780 | 
             
                                logging.error(f"Erro no modelo {model_key}: {e}")
         | 
| 781 | 
            +
                                sentry_sdk.capture_exception(e)
         | 
| 782 |  | 
| 783 | 
             
            def handle_generative_models(models, model_key):
         | 
| 784 | 
             
                """Manipula modelos generativos"""
         | 
|  | |
| 802 | 
             
                    if prompt.strip():
         | 
| 803 | 
             
                        with st.spinner("Criando imagem..."):
         | 
| 804 | 
             
                            try:
         | 
| 805 | 
            +
                                model = models.get(model_key) or load_model(model_key)
         | 
| 806 | 
            +
                                result = model(
         | 
| 807 | 
             
                                    prompt,
         | 
| 808 | 
             
                                    height=height,
         | 
| 809 | 
             
                                    width=width,
         | 
|  | |
| 811 | 
             
                                    guidance_scale=guidance_scale
         | 
| 812 | 
             
                                )
         | 
| 813 | 
             
                                display_results(result, model_key)
         | 
|  | |
| 814 | 
             
                            except Exception as e:
         | 
| 815 | 
             
                                st.error(f"Erro ao gerar imagem: {str(e)}")
         | 
| 816 | 
             
                                logging.error(f"Erro no modelo text-to-image: {e}")
         | 
| 817 | 
            +
                                sentry_sdk.capture_exception(e)
         | 
| 818 | 
             
                    else:
         | 
| 819 | 
             
                        st.warning("⚠️ Por favor, insira uma descrição para a imagem.")
         | 
| 820 |  |