import gradio as gr import uuid from ai_logic import ( responder_como_aldo, build_and_save_vector_store, MODELS, DEFAULT_MODEL, inicializar_sistema ) css_customizado = """ .gradio-container { max-width: 1400px !important; margin: 0 auto; width: 99%; height: 100vh !important; display: flex; flex-direction: column; overflow: hidden; } .main-content { display: flex; flex-direction: column; height: 100vh; overflow: hidden; flex-shrink: 0; } .titulo-principal { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; color: white !important; padding: 10px !important; border-radius: 10px !important; margin-bottom: 10px !important; text-align: center !important; flex-shrink: 0; } .chat-area { flex: 1; display: flex; flex-direction: column; overflow: hidden; } .chat-container { flex: 1; overflow-y: auto; margin-bottom: 10px; } .input-container { flex-shrink: 0; padding: 10px 0; display: flex; flex-direction: column; justify-content: center; } .additional-content { overflow-y: auto; padding-top: 20px; } /* Estilos para o chat - Melhorias na legibilidade */ .chatbot { height: 100% !important; max-height: none !important; } /* Mensagens do usuário */ .message.user { background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%) !important; color: white !important; border-radius: 18px 18px 6px 18px !important; padding: 12px 16px !important; margin: 8px 0 !important; font-size: 15px !important; line-height: 1.5 !important; box-shadow: 0 2px 8px rgba(79, 70, 229, 0.3) !important; border: none !important; } /* Mensagens do bot */ .message.bot { background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%) !important; color: #1e293b !important; border: 1px solid #e2e8f0 !important; border-radius: 18px 18px 18px 6px !important; padding: 16px 20px !important; margin: 8px 0 !important; font-size: 15px !important; line-height: 1.6 !important; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05) !important; } /* Estilização para código dentro das mensagens */ .message pre { background: #1e293b !important; color: #e2e8f0 !important; border-radius: 8px !important; padding: 16px !important; margin: 12px 0 !important; overflow-x: auto !important; font-family: 'Fira Code', 'Monaco', 'Menlo', 'Ubuntu Mono', monospace !important; font-size: 14px !important; line-height: 1.5 !important; border: 1px solid #374151 !important; } .message code { background: #e2e8f0 !important; color: #1e293b !important; padding: 2px 6px !important; border-radius: 4px !important; font-family: 'Fira Code', 'Monaco', 'Menlo', 'Ubuntu Mono', monospace !important; font-size: 13px !important; } /* Código inline dentro de pre */ .message pre code { background: transparent !important; color: #e2e8f0 !important; padding: 0 !important; border-radius: 0 !important; } /* Estilos específicos do Gradio para chatbot */ .chatbot .message-wrap { margin: 8px 0 !important; } .chatbot .message-wrap.user { justify-content: flex-end !important; } .chatbot .message-wrap.bot { justify-content: flex-start !important; } /* Melhorias na área de input */ #entrada_usuario textarea { background: linear-gradient(135deg, #1e293b 0%, #374151 100%) !important; color: white !important; font-size: 15px !important; line-height: 1.5 !important; border: 2px solid #374151 !important; border-radius: 12px !important; padding: 12px 16px !important; min-height: 60px !important; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1) !important; } #entrada_usuario textarea:focus { border-color: #4f46e5 !important; box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1) !important; } #entrada_usuario textarea::placeholder { color: #9ca3af !important; } /* Botão de enviar */ .gradio-button.primary { background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%) !important; border: none !important; border-radius: 12px !important; padding: 12px 24px !important; font-weight: 600 !important; font-size: 15px !important; transition: all 0.2s ease !important; } .gradio-button.primary:hover { transform: translateY(-1px) !important; box-shadow: 0 4px 12px rgba(79, 70, 229, 0.4) !important; } /* Dropdown do modelo */ .modelo-dropdown { margin-bottom: 15px !important; } .modelo-dropdown .gr-dropdown { border-radius: 8px !important; border: 1px solid #d1d5db !important; } /* Responsividade melhorada */ @media (max-width: 768px) { .titulo-principal { padding: 8px !important; font-size: 14px !important; } #entrada_usuario textarea { min-height: 50px !important; font-size: 16px !important; } .message.user, .message.bot { font-size: 14px !important; padding: 10px 14px !important; } .message pre { font-size: 12px !important; padding: 12px !important; } } /* Animações suaves */ .message { animation: fadeInUp 0.3s ease-out !important; } @keyframes fadeInUp { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } /* Melhorias gerais na tipografia */ .chatbot { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', sans-serif !important; } /* Scroll personalizado para o chat */ .chat-container::-webkit-scrollbar { width: 6px; } .chat-container::-webkit-scrollbar-track { background: #f1f5f9; border-radius: 3px; } .chat-container::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 3px; } .chat-container::-webkit-scrollbar-thumb:hover { background: #94a3b8; } /* Força aplicação dos estilos */ #component-6 { flex-grow: initial !important; } #component-7 { flex-grow: initial !important; } .message-wrap.svelte-gjtrl6 .prose.chatbot.md { opacity: 1 !important; } /* Estilo para links */ .message a { color: #4f46e5 !important; text-decoration: underline !important; } .message.user a { color: #e0e7ff !important; } /* Estilo para listas */ .message ul, .message ol { margin: 12px 0 !important; padding-left: 20px !important; } .message li { margin: 6px 0 !important; line-height: 1.6 !important; } /* Estilo para tabelas */ .message table { border-collapse: collapse !important; width: 100% !important; margin: 12px 0 !important; } .message th, .message td { border: 1px solid #d1d5db !important; padding: 8px 12px !important; text-align: left !important; } .message th { background: #f8fafc !important; font-weight: 600 !important; } """ def criar_interface(): with gr.Blocks(title="Dr. Aldo Henrique - API Externa", theme=gr.themes.Soft(), css=css_customizado) as interface: session_id_state = gr.State(str(uuid.uuid4())) # Geração do session_id único with gr.Column(elem_classes="main-content"): gr.HTML("""

🤖 iAldo - Converse com o Prof. Dr. Aldo Henrique

""") with gr.Column(elem_classes="chat-area"): with gr.Column(elem_classes="chat-container"): chatbot = gr.Chatbot( label="💬 Área do chat", elem_id="chat", height="100%", show_label=False, container=True, scale=1, min_width=160, visible=True, elem_classes="chatbot" ) with gr.Column(elem_classes="input-container"): with gr.Row(): modelo_select = gr.Dropdown( choices=list(MODELS.keys()), value=DEFAULT_MODEL, label="🧠 Selecione o Modelo de Pensamento", elem_classes="modelo-dropdown" ) with gr.Row(): user_input = gr.Textbox( show_label=False, placeholder="Digite sua pergunta e pressione Enter ou clique em Enviar", lines=2, elem_id="entrada_usuario", max_lines=6 ) enviar_btn = gr.Button("Enviar", variant="primary", size="lg") with gr.Column(elem_classes="additional-content"): with gr.Accordion("⚙️ Controle do Conhecimento (RAG)", open=False): status_rag = gr.Textbox(label="Status do Retreino", interactive=False) botao_retreinar = gr.Button("🔄 Atualizar Conhecimento do Blog", variant="stop") download_faiss_file = gr.File(label="Download do Índice FAISS", interactive=False, file_count="single", file_types=[".pkl"]) download_urls_file = gr.File(label="Download das URLs Processadas", interactive=False, file_count="single", file_types=[".pkl"]) with gr.Accordion("📚 Exemplos de Perguntas", open=False): gr.Examples( examples=[ ["Como implementar uma lista ligada em C com todas as operações básicas?", DEFAULT_MODEL], ["Qual a sua opinião sobre o uso de ponteiros em C++ moderno, baseada no seu blog?", "Mistral 7B (Mais acertivo)"], ["Resuma o que você escreveu sobre machine learning no seu blog.", "Zephyr 7B (Meio Termo)"], ], inputs=[user_input, modelo_select] ) with gr.Accordion("🔧 Status da API", open=False): status_api = gr.Textbox(label="Status dos Modelos", interactive=False, lines=8, value="Modelos carregados com sucesso! Verifique o console para detalhes.") with gr.Accordion("ℹ️ Informações", open=False): gr.Markdown(""" ### Sobre o Dr. Aldo Henrique: - **Especialidade**: Linguagens C, Java, Desenvolvimento Web, Inteligência Artificial - **Conhecimento Adicional**: Conteúdo do blog aldohenrique.com.br ### Dicas para melhores respostas: - Faça perguntas específicas sobre o conteúdo do blog para ver o RAG em ação! - Peça resumos ou opiniões sobre temas que o professor aborda. ### Melhorias na Interface: - **Mensagens do usuário**: Estilo moderno com gradiente azul/roxo - **Respostas do bot**: Fundo claro com excelente contraste para leitura - **Códigos**: Syntax highlighting com fundo escuro e fonte monospace - **Responsivo**: Otimizado para desktop e mobile """) def responder(chat_history, user_msg, modelo, session_id): if not user_msg.strip(): return chat_history, "" # Adiciona a mensagem do usuário ao histórico chat_history = chat_history + [[user_msg, "🤖 Dr. Aldo Henrique está digitando..."]] yield chat_history, "" try: # Obtem a resposta do modelo resposta_final = responder_como_aldo(session_id, user_msg, modelo) # Atualiza o histórico com a resposta final chat_history[-1][1] = resposta_final yield chat_history, "" except Exception as e: # Em caso de erro, mostra uma mensagem amigável chat_history[-1][1] = f"❌ Desculpe, ocorreu um erro ao processar sua mensagem: {str(e)}" yield chat_history, "" # Eventos de clique e submit enviar_btn.click( fn=responder, inputs=[chatbot, user_input, modelo_select, session_id_state], outputs=[chatbot, user_input], show_progress=True ) user_input.submit( fn=responder, inputs=[chatbot, user_input, modelo_select, session_id_state], outputs=[chatbot, user_input], show_progress=True ) botao_retreinar.click( fn=build_and_save_vector_store, outputs=[status_rag, download_faiss_file, download_urls_file], show_progress=True ) # Script para focar no input ao carregar a página gr.HTML(""" """) return interface def configurar_interface(): """ Configura a interface Gradio apenas se o sistema for inicializado com pelo menos 3 modelos disponíveis. Lança uma exceção com a lista de modelos disponíveis se a inicialização falhar. """ try: status, available_models = inicializar_sistema() if status: return criar_interface() else: 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'}" raise RuntimeError(error_msg) except Exception as e: print(f"Erro na configuração da interface: {e}") raise if __name__ == "__main__": try: app = configurar_interface() app.launch( server_name="0.0.0.0", server_port=7860, share=False, debug=False, show_error=True ) except Exception as e: print(f"Erro ao iniciar a aplicação: {e}") exit(1)