import streamlit as st import os from pathlib import Path from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings from llama_index.llms.gemini import Gemini from llama_index.embeddings.google import GoogleEmbedding import google.generativeai as genai import hashlib import hmac from typing import Optional # Configuração da página st.set_page_config( page_title="Anatomia - Material Didático", page_icon="📚", layout="wide" ) # Configuração da API do Google def setup_gemini(): """Configura o Gemini com a API key""" try: # Pegar API key dos secrets do Streamlit api_key = st.secrets.get("GOOGLE_API_KEY") if not api_key: st.error("❌ API Key do Google não encontrada! Configure nos secrets.") return False # Configurar o genai genai.configure(api_key=api_key) # Configurar o LLM Gemini llm = Gemini( model="models/gemini-1.5-flash", # Use gemini-1.5-pro para mais qualidade api_key=api_key, temperature=0.7, max_tokens=1024, ) # Configurar embeddings embed_model = GoogleEmbedding( model="models/embedding-001", api_key=api_key, ) # Configurar globalmente Settings.llm = llm Settings.embed_model = embed_model Settings.chunk_size = 512 Settings.chunk_overlap = 50 return True except Exception as e: st.error(f"❌ Erro ao configurar Gemini: {str(e)}") return False # Função para verificar senha def check_password(): """Verifica se a senha está correta""" def password_entered(): """Verifica se a senha inserida corresponde à senha armazenada""" if hmac.compare_digest( st.session_state["password"], st.secrets["PASSWORD"] ): st.session_state["password_correct"] = True del st.session_state["password"] else: st.session_state["password_correct"] = False # Retorna True se a senha estiver correta if st.session_state.get("password_correct", False): return True # Mostra o campo de senha col1, col2, col3 = st.columns([1, 2, 1]) with col2: st.markdown("### 🔒 Acesso Restrito") st.markdown("""
⚠️ Material protegido por direitos autorais
Este conteúdo é de uso exclusivo dos alunos da disciplina.
""", unsafe_allow_html=True) st.text_input( "Digite a senha de acesso:", type="password", on_change=password_entered, key="password", placeholder="Senha fornecida pelo monitor" ) if st.session_state.get("password_correct", False) is False and st.session_state.get("password"): st.error("❌ Senha incorreta! Acesso negado.") return False # Função para mostrar aviso de direitos autorais def show_copyright_notice(): with st.sidebar: st.image("https://cdn-icons-png.flaticon.com/512/2917/2917995.png", width=100) st.markdown("## 📚 Anatomia") st.markdown("---") st.markdown(""" ### ⚠️ **Aviso Legal** **Este material é protegido por direitos autorais.** #### É proibido: - ❌ Compartilhar o link de acesso - ❌ Baixar ou reproduzir o conteúdo - ❌ Distribuir o material por qualquer meio - ❌ Utilizar fora do contexto da disciplina #### © Todos os direitos reservados ao professor. """) st.markdown("---") st.markdown("### 📊 Estatísticas") if "messages" in st.session_state: st.metric("Perguntas realizadas", len(st.session_state.messages) // 2) st.markdown("---") st.markdown("### 💡 Dicas") st.info(""" **Para melhores resultados:** - Seja específico nas perguntas - Mencione estruturas anatômicas claramente - Pergunte sobre um tópico por vez """) # Função para carregar e processar os documentos @st.cache_resource def load_documents(): """Carrega os documentos e cria o índice""" try: # Verificar se existe a pasta data data_path = Path("data") if not data_path.exists(): st.warning("⚠️ Pasta 'data' não encontrada. Criando pasta...") data_path.mkdir(exist_ok=True) st.info("📁 Por favor, adicione os arquivos das aulas na pasta 'data'") return None # Verificar se há arquivos files = list(data_path.glob("*")) if not files: st.warning("⚠️ Nenhum arquivo encontrado na pasta 'data'") st.info("📄 Adicione os arquivos .txt, .pdf ou .docx das aulas") return None # Carregar documentos with st.spinner("📖 Carregando material didático..."): documents = SimpleDirectoryReader("data").load_data() if not documents: st.warning("⚠️ Nenhum documento válido encontrado") return None st.success(f"✅ {len(documents)} documentos carregados com sucesso!") # Criar índice with st.spinner("🔨 Construindo índice de busca..."): index = VectorStoreIndex.from_documents(documents) # Criar query engine com configurações personalizadas query_engine = index.as_query_engine( similarity_top_k=3, response_mode="compact", ) return query_engine except Exception as e: st.error(f"❌ Erro ao carregar documentos: {str(e)}") return None # Função para formatar resposta def format_response(response): """Formata a resposta para melhor visualização""" return response # Interface de chat def chat_interface(query_engine): """Interface principal de chat""" # Título principal st.markdown("""

🦴 Assistente Virtual de Anatomia

Tire suas dúvidas sobre o conteúdo das aulas

""", unsafe_allow_html=True) st.markdown("---") # Inicializar histórico de chat if "messages" not in st.session_state: st.session_state.messages = [] # Mostrar histórico for message in st.session_state.messages: with st.chat_message(message["role"]): st.markdown(message["content"]) # Input do usuário if prompt := st.chat_input("Digite sua pergunta sobre anatomia..."): # Adicionar mensagem do usuário st.session_state.messages.append({"role": "user", "content": prompt}) with st.chat_message("user"): st.markdown(prompt) # Gerar resposta with st.chat_message("assistant"): with st.spinner("🔍 Buscando no material didático..."): try: # Adicionar contexto de direitos autorais response = query_engine.query(prompt) # Exibir resposta st.markdown(response.response) # Adicionar fonte with st.expander("📖 Ver fonte no material"): st.info("Resposta baseada no material das aulas") st.session_state.messages.append( {"role": "assistant", "content": response.response} ) except Exception as e: st.error(f"❌ Erro ao processar pergunta: {str(e)}") st.info("💡 Tente reformular sua pergunta ou seja mais específico") # Função de boas-vindas def welcome_message(): """Mostra mensagem de boas-vindas""" st.markdown("""

🎓 Bem-vindo(a) ao Assistente de Anatomia!

Este assistente foi desenvolvido para ajudar você a estudar o conteúdo das aulas de Anatomia.

Como usar:

Exemplos de perguntas:

• Qual a função do osso esfenóide?
• Explique a estrutura do coração
• Quais são os músculos da respiração?
""", unsafe_allow_html=True) # Função principal def main(): # Verificar senha if not check_password(): st.stop() # Configurar Gemini if not setup_gemini(): st.stop() # Layout com sidebar show_copyright_notice() # Área principal col1, col2, col3 = st.columns([1, 3, 1]) with col2: # Carregar documentos query_engine = load_documents() if query_engine is None: st.warning(""" ### 📁 Adicione os arquivos das aulas Para começar a usar o assistente, você precisa: 1. Criar uma pasta chamada `data` na raiz do projeto 2. Adicionar os arquivos das aulas (.txt, .pdf ou .docx) 3. Aguardar o processamento automático Se você já adicionou os arquivos, aguarde alguns segundos. """) return # Mostrar mensagem de boas-vindas se não houver histórico if not st.session_state.get("messages", []): welcome_message() # Interface de chat chat_interface(query_engine) # Rodapé st.markdown("---") st.markdown("""

© Material didático protegido por direitos autorais - Uso exclusivo em sala de aula

Em caso de problemas técnicos, contate o monitor da disciplina

""", unsafe_allow_html=True) if __name__ == "__main__": main()