import gradio as gr from crewai import Task, LLM, Agent, Crew from xhtml2pdf import pisa import markdown import tempfile import os import io import hashlib from supabase import create_client import os # Set up the Supabase client # Replace these with your actual Supabase URL and key SUPABASE_URL = "https://wlriuezvfrsqfkvalabq.supabase.co" SUPABASE_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Indscml1ZXp2ZnJzcWZrdmFsYWJxIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDA4ODA1OTAsImV4cCI6MjA1NjQ1NjU5MH0.syhO_hTeiJb3To4_jAn2h9kXl0uDw_noMXTOuQwnwgE" supabase = create_client(SUPABASE_URL, SUPABASE_KEY) # Password hashing function def hash_password(password): return hashlib.sha256(password.encode()).hexdigest() # Login function using Supabase def login(username, password): try: # Query the 'usuario' table in Supabase response = supabase.table('usuario').select('*').eq('login', username).execute() # Check if user exists and password matches if response.data and len(response.data) > 0: stored_hash = response.data[0].get('senha') if stored_hash == hash_password(password): return True, f"Bem-vindo, {username}!" else: return False, "Senha incorreta. Tente novamente." else: return False, "Usuário não encontrado. Tente novamente." except Exception as e: print(f"Error during login: {e}") return False, "Erro ao fazer login. Por favor, tente novamente." # New registration function using Supabase def register_user(username, password, confirm_password): try: # Check if passwords match if password != confirm_password: return False, "As senhas não coincidem. Tente novamente." # Check if username already exists response = supabase.table('usuario').select('*').eq('login', username).execute() if response.data and len(response.data) > 0: return False, "Nome de usuário já existe. Escolha outro." # Hash the password hashed_password = hash_password(password) # Insert new user response = supabase.table('usuario').insert({ "login": username, "senha": hashed_password }).execute() # Check if insertion was successful if response.data: return True, "Cadastro realizado com sucesso! Você pode fazer login agora." else: return False, "Erro ao cadastrar usuário. Tente novamente." except Exception as e: print(f"Error during registration: {e}") return False, "Erro ao realizar cadastro. Por favor, tente novamente." # Function to create PDF from markdown def markdown_to_pdf(markdown_text): """ Convert markdown text to PDF content """ # Convert markdown to HTML html_text = markdown.markdown(markdown_text) # Add some basic styling styled_html = f"""
{html_text} """ # Create PDF from HTML content pdf_output = io.BytesIO() pisa.CreatePDF(styled_html, dest=pdf_output) pdf_output.seek(0) return pdf_output groqllm = LLM(model="groq/llama-3.3-70b-versatile") def executar_equipe_interface(disciplina, assunto, topicos_str): # Converter a string de tópicos para uma lista topicos = [t.strip() for t in topicos_str.split(',') if t.strip()] solicitacao = { "disciplina": disciplina, "assunto": assunto, "topicos": topicos } disciplina = solicitacao['disciplina'] assunto = solicitacao['assunto'] topicos = ', '.join(solicitacao['topicos']) agentMotivador = Agent( role='Motivador', goal='Escrever uma mensagem motivacional para o estudante.', backstory='Você é um coach motivacional com experiência em ajudar estudantes a manterem o foco.', llm=groqllm ) agentPlano = Agent( role='Coordenador de Estudos', goal=f'Sua tarefa é criar um plano de estudo estruturado com base nas seguintes informações: Disciplina: {disciplina}, Assunto: {assunto}, Tópicos: {topicos}', backstory='Você é um especialista em educação com experiência em criar planos de estudos eficientes.', llm=groqllm ) agentMaterialVideo = Agent( role='Pesquisador de Material', goal=f'Sua tarefa é pesquisar no Youtube por vídeos que explique as Disciplina: {disciplina} sobre o Assunto: {assunto} e seus Tópicos: {topicos}', backstory='Você é um especialista em educação com experiência em criar planos de estudos eficientes.', llm=groqllm ) tarefaMotivar = Task( description='Escrever uma mensagem motivacional para o estudante.', agent=agentMotivador, expected_output='Dois parágrafos com uma Mensagem motivacional em markdown.', ) tarefaGerarPlano = Task( description=f'Criar um plano de estudo estruturado com base nas seguintes informações: Disciplina: {disciplina}, Assunto: {assunto}, Tópicos: {topicos}.', agent=agentPlano, expected_output='Plano de estudos personalizado em markdown', ) tarefaBuscarVideos = Task( description=f'Pesquisar no Youtube por vídeos que explique as Disciplina: {disciplina} sobre o Assunto: {assunto} e seus Tópicos: {topicos}', agent=agentMaterialVideo, expected_output='Lista de vídeos relacionados ao assunto em markdown.', ) saida1 = agentMotivador.execute_task(tarefaMotivar) saida2 = agentPlano.execute_task(tarefaGerarPlano) saida3 = agentMaterialVideo.execute_task(tarefaBuscarVideos) saida_final = f"{saida1}\n\n{saida2}\n\n{saida3}" # Generate PDF from the output pdf_output = markdown_to_pdf(saida_final) # Save the PDF to a temporary file temp_dir = tempfile.gettempdir() pdf_filename = f"material_estudo_{hash_password(saida_final)[:8]}.pdf" pdf_path = os.path.join(temp_dir, pdf_filename) with open(pdf_path, 'wb') as f: f.write(pdf_output.getbuffer()) return saida_final, pdf_path def main_app(): # Load CSS from external file css_path = os.path.join(os.path.dirname(__file__), "static", "styles.css") try: with open(css_path, "r") as css_file: custom_css = css_file.read() except FileNotFoundError: # Fallback in case the file is not found print(f"Warning: CSS file not found at {css_path}") custom_css = "" with gr.Blocks(theme=gr.themes.Soft(), css=custom_css) as app: # Authentication state is_logged_in = gr.State(False) current_user = gr.State("") # Login Interface with gr.Group(visible=True) as login_block: with gr.Column(elem_classes=["main-container"]): with gr.Row(elem_classes=["header"]): gr.Markdown("# Sistema de Material de Estudo") gr.Markdown("### Assistente Inteligente para Geração de Material Educacional") with gr.Column(elem_classes=["login-container"]): gr.Markdown("### Login") with gr.Group(): username_input = gr.Textbox(label="Usuário", placeholder="Digite seu nome de usuário") password_input = gr.Textbox(label="Senha", type="password", placeholder="Digite sua senha") login_message = gr.Textbox(label="", interactive=False, visible=False) with gr.Row(): login_button = gr.Button("Entrar", variant="primary") with gr.Row(elem_classes=["register-link"]): gr.Markdown("Não tem uma conta?") register_nav_button = gr.Button("Cadastre-se", size="sm") with gr.Accordion("Informação", open=False): gr.Markdown(""" Por favor insira suas credenciais para acessar o sistema. """) # Registration Interface with gr.Group(visible=False) as register_block: with gr.Column(elem_classes=["main-container"]): with gr.Row(elem_classes=["header"]): gr.Markdown("# Sistema de Material de Estudo") gr.Markdown("### Cadastro de Novo Usuário") with gr.Column(elem_classes=["login-container"]): with gr.Group(): new_username = gr.Textbox(label="Nome de Usuário", placeholder="Escolha um nome de usuário") new_password = gr.Textbox(label="Senha", type="password", placeholder="Digite uma senha segura") confirm_password = gr.Textbox(label="Confirmar Senha", type="password", placeholder="Digite a senha novamente") register_message = gr.Textbox(label="", interactive=False, visible=False) with gr.Row(): back_button = gr.Button("Voltar", variant="secondary") register_button = gr.Button("Cadastrar", variant="primary") with gr.Accordion("Informação", open=False): gr.Markdown(""" Crie uma conta para acessar o sistema de geração de materiais de estudo. """) # Main Application Interface with gr.Group(visible=False) as main_block: with gr.Column(elem_classes=["main-container"]): with gr.Row(elem_classes=["user-info"]): user_display = gr.Markdown("Bem-vindo!") logout_button = gr.Button("Sair", size="sm") gr.Markdown("# Gerador Inteligente de Material de Estudos") gr.Markdown("### Personalize seu material educacional completo em minutos") with gr.Column(elem_classes=["form-card"]): gr.Markdown("### Dados do Material") with gr.Row(): with gr.Column(scale=1): disciplina_input = gr.Textbox( label="Disciplina", placeholder="Ex: Matemática, Física, História...", value="Matemática" ) with gr.Column(scale=1): assunto_input = gr.Textbox( label="Assunto", placeholder="Ex: Funções, Leis de Newton, Segunda Guerra Mundial...", value="Funções" ) topicos_input = gr.Textbox( label="Tópicos (separados por vírgula)", placeholder="Ex: Função quadrática, Função exponencial, Função logarítmica...", value="Função quadrática, Função exponencial, Função logarítmica", lines=2 ) with gr.Row(): generate_button = gr.Button("Gerar Material de Estudo", variant="primary", size="lg") # Progress indicator during generation with gr.Group(visible=False) as progress_group: progress_bar = gr.Progress() progress_text = gr.Markdown("Gerando material, por favor aguarde...") # Output tabs with gr.Tabs() as tabs: with gr.TabItem("Visualizar Material"): markdown_output = gr.Markdown(label="Material Completo") with gr.TabItem("Download"): with gr.Column(): gr.Markdown("### Download do Material") pdf_output = gr.File(label="Download PDF") gr.Markdown("Clique no botão acima para baixar seu material em formato PDF.") # Login function with improved feedback def login_fn(username, password): success, message = login(username, password) if success: return [ gr.update(visible=False), # login_block gr.update(visible=True), # main_block gr.update(value=message, visible=False), # login_message f"**Usuário:** {username}", # user_display True, # is_logged_in username # current_user ] else: return [ gr.update(visible=True), # login_block gr.update(visible=False), # main_block gr.update(value=message, visible=True), # login_message "", # user_display False, # is_logged_in "" # current_user ] # Logout function def logout_fn(): return [ gr.update(visible=True), # login_block gr.update(visible=False), # main_block "", # username_input "", # password_input gr.update(value="", visible=False), # login_message False, # is_logged_in "" # current_user ] # Registration function def register_fn(username, password, confirm_password): success, message = register_user(username, password, confirm_password) if success: # Return to login screen with success message return [ gr.update(visible=False), # register_block gr.update(visible=True), # login_block gr.update(value=message, visible=True), # login_message "", # new_username "", # new_password "", # confirm_password gr.update(value="", visible=False) # register_message ] else: return [ gr.update(visible=True), # register_block gr.update(visible=False), # login_block gr.update(value="", visible=False), # login_message username, # new_username (preserve input) "", # new_password "", # confirm_password gr.update(value=message, visible=True) # register_message ] # Navigation functions def show_register(): return [ gr.update(visible=False), # login_block gr.update(visible=True), # register_block gr.update(value="", visible=False) # login_message ] def show_login(): return [ gr.update(visible=False), # register_block gr.update(visible=True), # login_block gr.update(value="", visible=False) # register_message ] # Generate material function with progress tracking def generate_material(disciplina, assunto, topicos, progress=gr.Progress()): # Show progress during generation progress(0, desc="Iniciando geração do material...") # First phase - motivational content progress(0.25, desc="Gerando conteúdo motivacional...") # Second phase - study plan progress(0.5, desc="Elaborando plano de estudos...") # Third phase - gathering video resources progress(0.75, desc="Pesquisando recursos de vídeo...") # Execute the actual material generation markdown, pdf = executar_equipe_interface(disciplina, assunto, topicos) # Complete progress(1.0, desc="Material gerado com sucesso!") return [ markdown, # markdown_output pdf, # pdf_output gr.update(visible=False) # progress_group ] # Show progress during generation def show_progress(): return gr.update(visible=True) # progress_group # Connect buttons to functions login_button.click( login_fn, inputs=[username_input, password_input], outputs=[login_block, main_block, login_message, user_display, is_logged_in, current_user] ) logout_button.click( logout_fn, outputs=[login_block, main_block, username_input, password_input, login_message, is_logged_in, current_user] ) # Registration navigation buttons register_nav_button.click( show_register, outputs=[login_block, register_block, login_message] ) back_button.click( show_login, outputs=[register_block, login_block, register_message] ) # Registration form submission register_button.click( register_fn, inputs=[new_username, new_password, confirm_password], outputs=[register_block, login_block, login_message, new_username, new_password, confirm_password, register_message] ) generate_button.click( show_progress, outputs=[progress_group] ).then( generate_material, inputs=[disciplina_input, assunto_input, topicos_input], outputs=[markdown_output, pdf_output, progress_group] ) return app # Launch the application if __name__ == "__main__": app = main_app() app.launch()