PaperFlow / app.py
mariusjabami's picture
Update app.py
c3356b3 verified
raw
history blame
19.1 kB
import os
from time import sleep
from dotenv import load_dotenv
from google import genai
from reportlab.platypus import Paragraph, Frame
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.pagesizes import A4
from reportlab.lib.utils import ImageReader
from reportlab.pdfgen import canvas
load_dotenv()
api_token = os.environ.get("SYNAP")
class Model():
def __init__(self, titulo_pdf, titulo, n_paginas):
self.titulo = titulo
self.n_paginas = n_paginas
self.oppo = genai.Client(api_key=api_token, http_options={"api_version": "v1beta"})
print(f"Escolhendo os Subtemas")
self.subtemas = self.API(f"Sobre o tema {titulo} cria no total {self.n_paginas} subtemas para um trabalho academico, e sempre começa com a introdução mas não inclui a conclusão, e deixa nesse formato, Nome_do_subtema - tem que estar tudo junto separado por _, nomes curtos , apenas quero ver os temas, mais nenhuma outra resposta, tudo limpo so com os temas, nao pode ter espaco, tudo precisa estar ligado com _ ou -, mais nenhuma coisa, só os temas separados com _, por exemplo, Redes Neurais pode virar Redes_Neurais, separa com _ e não com -. Subtemas Curtos e devem vir bem escritos e acentuados e curtos (TEMAS CURTOS)").split()
sleep(5)
print(f"Subtemas Escolhidos!")
self.largura, self.altura = A4
self.c = canvas.Canvas(titulo_pdf, pagesize=A4)
self.pagina = 0
self.pagina_idc = 0
def capa(self, logo, capaImage, titulo, subtitulo, instituto):
self.logo = ImageReader(logo)
self.capaImage = ImageReader(capaImage)
self.titulo = titulo
self.instituto = instituto
self.professor = professor
x = (self.largura - 350)
y = self.altura - 150
self.c.drawImage(self.logo, x + 15, y, width=100, height=100)
self.c.setFont("Times-Roman", 10)
self.c.drawCentredString(x + 65, 675, "República de Angola")
self.c.setFont("Times-Roman", 10)
self.c.drawCentredString(x + 65, 660, "Ministério da Educação")
self.c.setFont("Times-Roman", 10)
self.c.drawCentredString(x + 65, 645, instituto)
self.c.setFont("Times-Bold", 35)
self.c.drawCentredString(x + 65, 580, titulo)
self.c.setFont("Times-Roman", 20)
self.c.drawCentredString(x + 65, 550, subtitulo)
self.c.drawImage(self.capaImage, (x - 65) / 2, (self.altura - 610), width=(576 + 270)/2, height=(315 + 200)/2)
margem = 20
self.c.rect(margem, margem, self.largura - 2*margem, self.altura - 2*margem)
self.c.setFont("Times-Roman", 15)
self.c.drawCentredString(x + 165, 150, "Docente")
self.c.line(320, 100, 490, 100)
def integrantes(self, integrantes, disciplina, grupo, classe, turma, curso, turno):
self.c.showPage()
self.paginar_letra("I")
y = 700
self.c.setFont("Times-Bold", 20)
self.c.drawCentredString(200, 750, "Integrantes do Grupo")
self.integrantes = integrantes
numero = 1
for i in integrantes:
self.c.setFont("Times-Roman", 15)
self.c.drawString(110, y, f"{numero}.")
self.c.drawString(130, y, f"{i}")
y -= 25
numero += 1
self.c.setFont("Times-Bold", 15)
self.c.drawString(110, 300, "Disciplina: ")
self.c.setFont("Times-Roman", 15)
self.c.drawString(190, 300, disciplina)
self.c.setFont("Times-Bold", 15)
self.c.drawString(110, 280, "Grupo: ")
self.c.setFont("Times-Roman", 15)
self.c.drawString(165, 280, grupo)
self.c.setFont("Times-Bold", 15)
self.c.drawString(110, 260, "Classe: ")
self.c.setFont("Times-Roman", 15)
self.c.drawString(165, 260, classe)
self.c.setFont("Times-Bold", 15)
self.c.drawString(110, 240, "Turma: ")
self.c.setFont("Times-Roman", 15)
self.c.drawString(165, 240, turma)
self.c.setFont("Times-Bold", 15)
self.c.drawString(110, 220, "Curso: ")
self.c.setFont("Times-Roman", 15)
self.c.drawString(165, 220, curso)
self.c.setFont("Times-Bold", 15)
self.c.drawString(110, 200, "Turno: ")
self.c.setFont("Times-Roman", 15)
self.c.drawString(165, 200, turno)
def agradecimentos(self, prof):
prompt = f"Cria uma nota de agradecimentos, imagina que um grupo escolara fez um trabalho academico e precisa fazer a parte dos agradecimentos, agradecer a Jesus Cristo e professor/a {prof}, OBS: a nota deve ser pequena, umas 4 linhas, não deve conter simbolos como ** ## ou outro, apenas texto puro, faz om agradecimento de forma geral, sem citar nós como alunos ou turma, apenas agradecendo"
print(f"Criando os Agradecimentos - Página {self.pagina}")
texto = self.API(prompt)
sleep(5)
self.c.showPage()
self.paginar_letra("II")
self.c.setFont("Times-Bold", 17)
self.c.drawCentredString(595/2, 750, "Agradecimentos")
styles = getSampleStyleSheet()
text = f"{texto}"
meust = ParagraphStyle(
"Marius",
parent=styles["Normal"],
fontName="Times-Roman",
fontSize=12,
alignment=4
)
frame = Frame(100, 100, 400, 630, showBoundary=0)
p = Paragraph(text, meust)
frame.addFromList([p], self.c)
def dedicatoria(self):
prompt = f"É um trabalho academico, cria uma dedicatoria pequena sobre a startup de criação de software CloseSource de Marius Jabami, uma nota meio pequena, umas 8 linhas, só quero a dedicatoria e mais nada, OBS: não usa simbolos como ** ou ##, podes usar tags html para negritar como <strong>"
print(f"Criando a Dedicatória - Página {self.pagina}")
texto = self.API(prompt)
sleep(5)
self.c.showPage()
self.paginar_letra("III")
self.c.setFont("Times-Bold", 17)
self.c.drawCentredString(595/2, 750, "Dedicatória")
styles = getSampleStyleSheet()
text = f"{texto}"
meust = ParagraphStyle(
"Marius",
parent=styles["Normal"],
fontName="Times-Roman",
fontSize=12,
alignment=4
)
frame = Frame(100, 100, 400, 630, showBoundary=0)
p = Paragraph(text, meust)
frame.addFromList([p], self.c)
def epigrafe(self):
prompt = "Manda uma frase famosa e aleatoria, com duplos sentidos, OBS: apenas quero a frase, mais nada escrito, interface totalmente limpa, nao usar simbolos como ** ##, apenas texto puro"
print(f"Criando a Epígrafe - Página {self.pagina}")
texto = self.API(prompt)
sleep(5)
self.c.showPage()
self.paginar_letra("IV")
self.c.setFont("Times-Bold", 17)
self.c.drawCentredString(595/2, 750, "Epígrafe")
styles = getSampleStyleSheet()
text = f'"{texto}"'
meust = ParagraphStyle(
"Marius",
parent=styles["Normal"],
fontName="Times-Italic",
fontSize=12,
alignment=2
)
frame = Frame(400, -350, 170, 630, showBoundary=0)
p = Paragraph(text, meust)
frame.addFromList([p], self.c)
def resumo(self):
prompt = f"Faz um resumo sobre o tema {self.titulo} em um trabalho academico, dizendo de forma geral o que o trabalho vai abordar OBS: nao usa simbolos como ** ou ##, quero apenas texto puro e apenas o resumo, sem nenhuma outra coisa, e usa <br/> usar dois para quebrar linha de preferência"
print(f"Criando o Resumo - Página {self.pagina}")
texto = self.API(prompt)
sleep(5)
self.c.showPage()
self.paginar_letra("V")
self.c.setFont("Times-Bold", 17)
self.c.drawCentredString(595/2, 750, "Resumo")
styles = getSampleStyleSheet()
text = f"{texto}"
meust = ParagraphStyle(
"Marius",
parent=styles["Normal"],
fontName="Times-Roman",
fontSize=12,
alignment=4
)
frame = Frame(100, 100, 400, 630, showBoundary=0)
p = Paragraph(text, meust)
frame.addFromList([p], self.c)
def indice(self):
print(f"Criando Índice - Página {self.pagina}")
self.c.showPage()
self.paginar_letra("VI")
y = 700
self.c.setFont("Times-Bold", 20)
self.c.drawCentredString(595/2, 750, "Índice")
temas = []
for i in self.subtemas:
temas.append(i.replace("_", " "))
x_inicial = 110
x_limite = 500
temas.append("Conclusão")
temas.append("Referências Bibliográficas")
for nome in temas:
self.pagina_idc +=1
self.c.setFont("Times-Roman", 15)
self.c.drawString(x_inicial, y, f"{nome} ")
largura_nome = self.c.stringWidth(nome, "Times-Roman", 15)
x_atual = x_inicial + largura_nome
largura_ponto = self.c.stringWidth(".", "Times-Roman", 15)
while x_atual + largura_ponto < x_limite:
self.c.drawString(x_atual, y, ".")
x_atual += largura_ponto
if nome == "Conclusão":
self.c.drawString(x_limite + 10, y, "I")
elif nome == "Referências Bibliográficas":
self.c.drawString(x_limite + 10, y, "II")
else:
self.c.drawString(x_limite + 10, y, str(self.pagina_idc))
y -= 25
def desenvolvimento(self):
sub = self.subtemas
sub.append("Conclusão")
temas = []
for t in sub:
temas.append(t.replace("_", " "))
for subtemas in temas:
prompt = f"""
Você é um assistente especializado em produzir DSENVOLVIMENTOS DE TEXTOS ACADÊMICOS claros, objetivos e bem estruturados.
INSTRUÇÕES OBRIGATÓRIAS:
- Tema principal: {self.titulo}
- Subtema a desenvolver: {subtemas}
FORMATO E ESTILO:
1. A saída deve conter APENAS o texto do desenvolvimento. Não inclua títulos, cabeçalho, explicações, notas, listas, metadados ou qualquer tipo de marcação extra.
2. Não utilize símbolos de Markdown (como **, ##, ###, ``` ou blocos de código). NÃO PRODUZA MARKDOWN.
3. São permitidas apenas as seguintes tags HTML:
- `<br/>` para uma quebra curta de linha dentro de um parágrafo.
- `<br/><br/>` para separar parágrafos (OBRIGATÓRIO: cada novo parágrafo deve começar após exatamente `<br/><br/>`).
- `<strong>...</strong>` para negrito.
4. Não utilize listas com “-”, “*”, “1.” ou similares; escreva em parágrafos contínuos.
5. Não inclua citações, referências, URLs ou notas explicativas.
6. Mantenha tom objetivo, técnico e adequado ao nível informado, evitando qualquer linguagem promocional.
7. Não mistura paragrafos, eles devem ter no maximo 5 linhas, evita misturas, quebre linha sempre que poder
8. Se o subtema for extenso nao tenha medo de desenvolver muito mais
CONTEÚDO:
- Apresente uma definição breve do subtema no contexto do tema principal.
- Desenvolva de 2 a 4 ideias centrais essenciais para compreender o subtema.
- Finalize com uma frase conclusiva que sintetize a relevância do subtema dentro do tema principal.
EXEMPLO DE FORMATO (não reproduzir no resultado):
Parágrafo 1...<br/><br/>Parágrafo 2 com <strong>termo importante</strong>...
ENTREGA:
- Responda somente com o desenvolvimento final.
- Não inclua linhas em branco extras no início ou no fim.
- Use `<br/><br/>` para separar parágrafos e `<strong>` apenas para destaque de termos essenciais.
DA O TEU MELHOR NA ORGANIZACAO, ORGANIZA MUITO BEM E SEM CONFUSÃO
Agora, seguindo rigorosamente todas as instruções acima, gere o resumo solicitado.
"""
print(f"Criando o Subtema {subtemas} - Página {self.pagina + 1}")
texto = self.API(prompt)
print(f"Subtema {subtemas} criado!")
sleep(10)
self.pagina += 1
self.c.showPage()
if subtemas == "Conclusão":
self.paginar_letra("I")
else:
self.paginar(self.pagina)
self.c.setFont("Times-Bold", 17)
self.c.drawCentredString(595/2, 750, subtemas)
styles = getSampleStyleSheet()
text = f"{texto}"
meust = ParagraphStyle(
"Marius",
parent=styles["Normal"],
fontName="Times-Roman",
fontSize=12,
alignment=4
)
frame = Frame(100, 100, 400, 630, showBoundary=0)
p = Paragraph(text, meust)
frame.addFromList([p], self.c)
def ref(self):
prompt = f"""
Você é um assistente que gera REFERÊNCIAS BIBLIOGRÁFICAS em formato padronizado.
TEMA: {self.titulo}
INSTRUÇÕES OBRIGATÓRIAS:
1. Gere EXATAMENTE 5 referências relacionadas ao tema informado.
2. Cada referência deve conter EXATAMENTE 3 linhas:
- 1ª linha: Autor(es) e ano.
- 2ª linha: Título da obra/artigo.
- 3ª linha: Link em formato HTML, usando exclusivamente <u>...</u>.
3. Cada referência deve ser separada da seguinte por exatamente `<br/><br/>`.
4. Não usar listas, não usar markdown, não usar negrito ou itálico nas referências.
5. Não adicionar explicações, textos extras ou comentários — apenas as referências no formato exigido.
6. As referências podem ser fictícias, mas devem parecer verossímeis.
FORMATO EXEMPLO (NÃO reproduzir os dados abaixo):
Autor, Ano
Título da obra
<u>link...</u><br/><br/>
Agora gere as 5 referências conforme o tema.
"""
print(f"Criando o Subtema Referências Bibliográficas - Página {self.pagina + 1}")
texto = self.API(prompt)
print(f" Trabalho finalizado criado!")
#sleep(7)
self.c.showPage()
self.pagina += 1
self.paginar_letra("II")
self.c.setFont("Times-Bold", 17)
self.c.drawCentredString(595/2, 750, "Referências Bibliográficas")
styles = getSampleStyleSheet()
text = f"{texto}"
meust = ParagraphStyle(
"Marius",
parent=styles["Normal"],
fontName="Times-Roman",
fontSize=12,
alignment=4
)
frame = Frame(100, 100, 400, 630, showBoundary=0)
p = Paragraph(text, meust)
frame.addFromList([p], self.c)
def paginar(self, pag):
self.c.drawString(500, 50, str(pag))
def paginar_letra(self, pag):
self.c.drawString(500, 50, pag)
def API(self, prompt):
while True:
try:
sleep(3)
print("Gerando...")
res = self.oppo.models.generate_content(model="gemma-3-27b-it", contents=prompt)
return self.limpar(res.text)
except Exception as e:
print("erro:", e)
print("Tentando novamente")
def limpar(self, texto):
texto = texto.replace("<img>", "&lt;img&gt;")
texto = texto.replace("<p>", "&lt;p&gt;").replace("</p>", "&lt;/p&gt;")
texto = texto.replace("<div>", "&lt;div&gt;").replace("</div>", "&lt;/div&gt;")
texto = texto.replace("<h1>", "&lt;h1&gt;").replace("</h1>", "&lt;/h1&gt;")
return texto
def save(self):
self.c.save()
def criar_trabalho(logo, capaImage, titulo, subtitulo, instituto, integrantes, prof, disciplina, grupo, classe, turma, curso, turno, n_paginas):
txt = [t[0] for t in integrantes]
txt1 = []
for i in txt:
txt1.append(i)
nn = Model(f"{titulo}.pdf", titulo, n_paginas)
nn.capa(logo, capaImage, titulo, subtitulo, instituto)
nn.integrantes(txt, disciplina, grupo, classe, turma, curso, turno)
nn.agradecimentos(prof)
nn.dedicatoria()
nn.epigrafe()
nn.resumo()
nn.indice()
nn.desenvolvimento()
nn.ref()
nn.save()
return f"{titulo}.pdf"
logo = "logo.png"
titulo = "Alcoolismo em Angola"
inst = "Complexo Escolar Politécnico Girassol"
professor = "Hélder Vunge"
capa = "images.png"
sub = "Alto nível de alcoolismo em Angola"
#criar_trabalho(logo, capa, titulo, sub, inst)
import numpy as np
import gradio as gr
with gr.Blocks(theme="NoCrypt/miku") as demo:
gr.Markdown("# PaperFlow - As tuas mãos invisíveis")
gr.Textbox(
label="ISSO PODE DEMORAR ~5MIN, MINHA CPU É RUINZINHA KKK",
value="DESENVOLVIDO PELA STARTUP CLOSESOURCE (CS)",
interactive=False
)
saida_do_pdf = gr.File(label="BAIXAR PDF")
with gr.Row():
logo = gr.Image(label="LOGO DO INSTITUTO OU ESCOLA", type="filepath")
capaImage = gr.Image(label="IMAGEM DA CAPA", type="filepath")
with gr.Row():
titulo = gr.Textbox(label="TÍTULO OU TEMA")
subtitulo = gr.Textbox(label="SUBTÍTULO")
instituto = gr.Textbox(label="INSTITUTO")
with gr.Row():
disciplina = gr.Textbox(label="DISCIPLINA")
grupo = gr.Textbox(label="GRUPO")
classe = gr.Textbox(label="CLASSE")
turma = gr.Textbox(label="TURMA")
curso = gr.Textbox(label="CURSO")
turno = gr.Textbox(label="TURNO")
with gr.Row():
professor = gr.Textbox(label="NOME DO PROFESSOR")
n_paginas = gr.Textbox(label="NÚMERO DE PÁGINAS (CONTEÚDO)")
integrantes = gr.DataFrame(
headers = ["Nome dos Integrantes"],
row_count=15,
col_count=1,
type="array",
interactive=True,
wrap=True
)
botao_criar = gr.Button("CRIAR TRABALHO")
botao_criar.click(fn=criar_trabalho, inputs=[logo, capaImage, titulo, subtitulo, instituto, integrantes, professor, disciplina, grupo, classe, turma, curso, turno, n_paginas], outputs=[saida_do_pdf])
demo.launch(share=True)