portalprogramando / interface.py
aldohenrique's picture
Update interface.py
245ca94 verified
raw
history blame
11.5 kB
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;
}
.gr-textbox textarea {
font-size: 14px !important;
line-height: 1.5 !important;
}
.resposta-container {
background-color: #ffffff !important;
color: #1a1a1a !important;
border: 1px solid #e0e0e0 !important;
border-radius: 20px !important;
padding: 20px !important;
margin: 10px 0 !important;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05) !important;
}
.resposta-container pre code {
color: #1a1a1a !important;
background-color: #f8f9fa !important;
}
.pergunta-container {
background-color: #f0f8ff !important;
border-radius: 8px !important;
padding: 15px !important;
}
.modelo-dropdown {
margin-bottom: 15px !important;
}
#entrada_usuario textarea {
color: white !important;
font-size: large !important;
background-color: #1a1a1a !important;
min-height: 60px !important;
}
.message-content {
opacity: 1 !important;
font-size: larger;
color: white !important;
background-color: #1a1a1a !important;
}
/* Responsivo */
@media (max-width: 768px) {
.titulo-principal {
padding: 10px !important;
}
#entrada_usuario textarea {
min-height: 50px !important;
font-size: 16px !important;
}
}
#component-6{flex-grow: initial !important;}
#component-7{flex-grow: initial !important;}
.message-wrap.svelte-gjtrl6 .prose.chatbot.md {
opacity: 1 !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("""
<div class="titulo-principal">
<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>
</div>
""")
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%"
)
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"
)
enviar_btn = gr.Button("Enviar", variant="primary")
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.
""")
def responder(chat_history, user_msg, modelo, session_id):
if not user_msg.strip():
return chat_history, ""
chat_history = chat_history + [[user_msg, "Dr. Aldo Henrique está digitando..."]]
yield chat_history, ""
resposta_final = responder_como_aldo(session_id, user_msg, modelo)
chat_history[-1][1] = resposta_final
yield chat_history, ""
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
)
gr.HTML("""
<script>
window.addEventListener("load", function() {
const textarea = document.querySelector("#entrada_usuario textarea");
if textarea {
setTimeout(() => textarea.focus(), 100);
}
});
</script>
""")
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 se a inicialização falhar.
"""
if inicializar_sistema():
return criar_interface()
else:
raise RuntimeError("Não foi possível inicializar o sistema: menos de 3 modelos de IA disponíveis. Verifique os logs para mais detalhes.")
if __name__ == "__main__":
app = configurar_interface()
app.launch()
```
#### `app.py`
<xaiArtifact artifact_id="c5068ba0-fdc1-4a4b-b129-a50cb274523b" artifact_version_id="af79201f-aca2-42e0-b3bf-5de749c8666d" title="app.py" contentType="text/python">
```python
#!/usr/bin/env python3
"""
Dr. Aldo Henrique - Chatbot com RAG
Arquivo principal que inicializa o sistema e lança a interface Gradio.
"""
import os
import gradio as gr
from interface import configurar_interface
# 🔑 Token do Hugging Face vindo das variáveis de ambiente
HF_TOKEN = os.getenv("HF_TOKEN")
def main():
"""
Função principal que gerencia o fluxo de inicialização do chatbot:
1. Verifica a presença do token Hugging Face.
2. Tenta configurar a interface Gradio (que internamente testa os modelos).
3. Lança a interface completa ou uma página de erro, dependendo do resultado.
"""
print("🚀 Iniciando Dr. Aldo Henrique com RAG...")
# --- 1. Verificar se o token HF está configurado ---
if not HF_TOKEN:
print("❌ Erro: Token HF_TOKEN não encontrado nas variáveis de ambiente.")
print("A interface não será carregada. Por favor, defina a variável de ambiente HF_TOKEN.")
error_app_no_token = gr.Blocks()
with error_app_no_token:
gr.Markdown("<h1>Erro: Token HF_TOKEN não encontrado.</h1><p>Por favor, defina a variável de ambiente **HF_TOKEN** para iniciar o sistema.</p>")
error_app_no_token.launch(
server_name="0.0.0.0",
server_port=7860,
share=False,
show_error=True
)
return
print(f"🔑 Token HF encontrado: {HF_TOKEN[:8]}...")
# --- 2. Configurar a interface ---
try:
app_to_launch = configurar_interface()
print("🌐 Interface configurada com sucesso. Lançando...")
# --- 3. Lançar a aplicação ---
if isinstance(app_to_launch, (gr.Blocks, gr.Interface)):
app_to_launch.launch(
server_name="0.0.0.0",
server_port=7860,
share=False,
max_threads=8,
show_error=True
)
else:
print("Erro inesperado: configurar_interface retornou um tipo de objeto desconhecido.")
unexpected_error_app = gr.Blocks()
with unexpected_error_app:
gr.Markdown("<h1>Erro Inesperado</h1><p>Ocorreu um erro desconhecido ao configurar a interface. Por favor, entre em contato com o suporte.</p>")
unexpected_error_app.launch(
server_name="0.0.0.0",
server_port=7860,
share=False,
show_error=True
)
except RuntimeError as e:
print(f"❌ Erro ao configurar a interface: {str(e)}")
error_app = gr.Blocks()
with error_app:
gr.Markdown(f"<h1>Erro de Inicialização</h1><p>{str(e)}</p><p>Por favor, verifique a conexão com o Hugging Face e o token de acesso, ou consulte os logs para mais detalhes.</p>")
error_app.launch(
server_name="0.0.0.0",
server_port=7860,
share=False,
show_error=True
)
if __name__ == "__main__":
main()