Spaces:
Sleeping
Sleeping
| 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> | |
| <head> | |
| <style> | |
| body {{ font-family: Arial, sans-serif; margin: 20px; }} | |
| h1 {{ color: #2c3e50; }} | |
| h2 {{ color: #3498db; }} | |
| h3 {{ color: #2980b9; }} | |
| a {{ color: #3498db; }} | |
| </style> | |
| </head> | |
| <body> | |
| {html_text} | |
| </body> | |
| </html> | |
| """ | |
| # 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() | |