Spaces:
Sleeping
Sleeping
File size: 8,021 Bytes
9ee83a7 21a2300 9ee83a7 21a2300 9ee83a7 21a2300 9ee83a7 21a2300 9ee83a7 21a2300 9ee83a7 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
import os
import hashlib
from subprocess import call
from shiny import App, reactive, render, ui
from core.read_pdf import process_pdf, temp_dir
from core.chatgpt.utils import generate_latex_slide
last_pdf_md5_preprocess_stage = None
def compute_hash(file_pth):
with open(file_pth, 'rb') as file_to_check:
# read contents of the file
data = file_to_check.read()
# pipe contents of the file through
md5_returned = hashlib.md5(data).hexdigest()
return md5_returned
def ui_card(title, *args):
return (ui.div(
{"class": "card mb-4"},
ui.div(title, class_="card-header"),
ui.div({"class": "card-body"}, *args),
), )
app_ui = ui.page_fluid(
ui.h1("Document2Slide Demo"),
ui_card(
"Upload PDF and Preprocess",
ui.input_file("input_pdf", "Choose a .pdf file to upload:", multiple=False),
ui.output_text("upload_file_status", ),
ui.p(
ui.input_action_button("preprocess_action", "Preprocess file", class_="btn-primary"),
ui.output_text("preprocess_result", ),
),
ui.output_text("preprocess_status", ),
ui.download_button("download_preprocessed", "Download preprocessed file"),
),
ui.h3("Due to gpt-4's unreliable service, we choose to show our demo locally. You can refer to ./core/chatgpt/generate_slides.py for this pipeline."),
ui_card(
"Upload the generated bullet points in pre-defined format.",
ui.input_file("input_bullet", "Choose a .tex bullet-point file to upload:", multiple=False),
ui.output_text("upload_bullet_status", ),
ui.p(
ui.input_action_button("process_bullet", "Generate .tex", class_="btn-primary"),
ui.output_text("process_bullet_result", ),
),
ui.p(ui.download_button("download_beamer", "Download beamer source code")),
ui.p(
ui.input_action_button("complie_latex", "Compile the latex file generated before.", class_="btn-primary"),
ui.output_text("complie_latex_result", ),
),
ui.p(ui.download_button("download_slide", "Download slide generated")),
),
)
def server(input, output, session):
@output
@render.text
def upload_file_status():
file_infos = input.input_pdf()
# print(file_infos) # [{'name': 'Poster.pdf', 'size': 598394, 'type': 'application/pdf', 'datapath': '/tmp/fileupload-2c21fv0a/tmpi91sy07h/0.pdf'}]
if not file_infos:
return "There is no file provided currently."
elif file_infos[0]['type'] != 'application/pdf':
return "the file you provide is not in PDF format, upload another one!"
else:
return "PDF file successfully uploaded!"
@output
@render.text
def preprocess_status():
global last_pdf_md5_preprocess_stage
file_infos = input.input_pdf()
file_md5 = compute_hash(file_infos[0]['datapath']) if file_infos else None
if (file_infos is not None) and file_infos[0]['type'] == 'application/pdf' and (file_md5 != last_pdf_md5_preprocess_stage):
return "Ready to preprocess the PDF!"
elif file_md5 == last_pdf_md5_preprocess_stage:
return "PDF already preprocessed! You can continue!"
else:
return "No PDF ready currently, please upload a PDF!"
@output
@render.text
@reactive.event(input.preprocess_action) # Take a dependency on the button
async def preprocess_result():
global last_pdf_md5_preprocess_stage
file_infos = input.input_pdf()
if (file_infos is not None) and file_infos[0]['type'] == 'application/pdf':
file_name = file_infos[0]['name']
original_pdf_pth = file_infos[0]['datapath']
dir_name = os.path.dirname(original_pdf_pth)
new_pdf_pth = os.path.join(dir_name, file_name)
os.rename(original_pdf_pth, new_pdf_pth)
file_infos[0]['datapath'] = new_pdf_pth
file_md5 = compute_hash(file_infos[0]['datapath'])
try:
if file_md5 != last_pdf_md5_preprocess_stage:
process_pdf(pdf_pth=new_pdf_pth, file_name=file_name)
last_pdf_md5_preprocess_stage = file_md5
return "Process successfully!"
else:
return "Already processed!!!"
except:
return "Something wrong happen, please switch to another file!"
else:
return "No PDF provided!"
@session.download()
def download_preprocessed():
file_infos = input.input_pdf()
file_name = file_infos[0]['name'][:-4]
preprocessed_file_dir = os.path.join(temp_dir, file_name)
if os.path.exists(preprocessed_file_dir): # this dir exists
args = ['zip', '-r', file_name + '.zip', './' + file_name]
call(args, cwd=temp_dir)
return str(os.path.join(temp_dir, file_name + '.zip'))
def upload_file_status():
file_infos = input.input_bullet()
# print(file_infos) # [{'name': 'Poster.pdf', 'size': 598394, 'type': 'application/pdf', 'datapath': '/tmp/fileupload-2c21fv0a/tmpi91sy07h/0.pdf'}]
if not file_infos:
return "There is no file provided currently."
elif file_infos[0]['type'] != 'text/plain':
return "the file you provide is not in txt format, upload another one!"
else:
return "txt file successfully uploaded!"
@output
@render.text
@reactive.event(input.process_bullet) # Take a dependency on the button
async def process_bullet_result():
file_infos = input.input_bullet()
file_name = file_infos[0]['name'] if file_infos else None
if (file_infos is not None) and file_infos[0]['type'] == 'text/plain':
txt_pth = file_infos[0]['datapath']
try:
with open(txt_pth, 'r') as f:
slide = f.read()
output_tex_pth = str(os.path.join(temp_dir, file_name[:-4] + '.tex'))
if not os.path.exists(temp_dir):
os.makedirs(temp_dir)
generate_latex_slide(slide, output_tex_pth)
return "Generate .tex file successful!"
except:
return "Something run happened please which to another file!"
else:
return "No .txt provided, please upload one!"
@session.download()
def download_beamer():
file_infos = input.input_bullet()
if not file_infos:
return
file_name = file_infos[0]['name']
tex_pth = str(os.path.join(temp_dir, file_name[:-4] + '.tex'))
if not os.path.exists(tex_pth):
return
else:
return tex_pth
@output
@render.text
@reactive.event(input.complie_latex) # Take a dependency on the button
async def complie_latex_result():
file_infos = input.input_bullet()
if not file_infos:
return "No file uploaded yet!"
file_name = file_infos[0]['name']
tex_pth = str(os.path.join(temp_dir, file_name[:-4] + '.tex'))
if not os.path.exists(tex_pth):
return "No .tex file yet, please upload a .txt bullet point file and convert it to beamer tex."
tex_file_name = tex_pth.split('/')[-1]
args = ["latexmk", "-xelatex", tex_file_name]
return_code = call(args, cwd=temp_dir)
if return_code == 0:
return "Compile sucessful!"
else:
return "Compile fail!"
@session.download()
def download_slide():
file_infos = input.input_bullet()
if not file_infos:
return
file_name = file_infos[0]['name']
pdf_pth = str(os.path.join(temp_dir, file_name[:-4] + '.pdf'))
if not os.path.exists(pdf_pth):
return
else:
return pdf_pth
app = App(app_ui, server)
|