study_plan_v2 / app.py
giseldo's picture
Update app.py
7278d33 verified
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()