Spaces:
Running
Running
import glob | |
import os | |
import random | |
import re | |
import string | |
import gradio as gr | |
import openai | |
from icrawler import ImageDownloader | |
from icrawler.builtin import GoogleImageCrawler, BingImageCrawler | |
from uuid import uuid4 | |
from pptx import Presentation | |
bad_coding_practice = ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in | |
range(16)) | |
def refresh_bad_coding_practice(): | |
global bad_coding_practice | |
bad_coding_practice = ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) | |
for _ in range(16)) | |
return | |
class PrefixNameDownloader(ImageDownloader): | |
def get_filename(self, task, default_ext): | |
filename = super(PrefixNameDownloader, self).get_filename( | |
task, default_ext) | |
print(bad_coding_practice) | |
return 'prefix_' + bad_coding_practice + filename | |
def generate_ppt(file, topic, slide_length, api_key): | |
print(file.name) | |
root = Presentation(file.name) | |
openai.api_key = api_key | |
message = f""" | |
Create content for a slideshow presentation. | |
The content's topic is {topic}. | |
The slideshow is {slide_length} slides long. | |
The content is written in the language of the content I give you above. | |
You are allowed to use the following slide types: | |
Slide types: | |
Title Slide - (Title, Subtitle) | |
Content Slide - (Title, Content) | |
Image Slide - (Title, Content, Image) | |
Thanks Slide - (Title) | |
Put this tag before the Title Slide: [L_TS] | |
Put this tag before the Content Slide: [L_CS] | |
Put this tag before the Image Slide: [L_IS] | |
Put this tag before the Thanks Slide: [L_THS] | |
Put "[SLIDEBREAK]" after each slide | |
For example: | |
[L_TS] | |
[TITLE]Mental Health[/TITLE] | |
[SLIDEBREAK] | |
[L_CS] | |
[TITLE]Mental Health Definition[/TITLE] | |
[CONTENT] | |
1. Definition: A person’s condition with regard to their psychological and emotional well-being | |
2. Can impact one's physical health | |
3. Stigmatized too often. | |
[/CONTENT] | |
[SLIDEBREAK] | |
Put this tag before the Title: [TITLE] | |
Put this tag after the Title: [/TITLE] | |
Put this tag before the Subitle: [SUBTITLE] | |
Put this tag after the Subtitle: [/SUBTITLE] | |
Put this tag before the Content: [CONTENT] | |
Put this tag after the Content: [/CONTENT] | |
Put this tag before the Image: [IMAGE] | |
Put this tag after the Image: [/IMAGE] | |
Elaborate on the Content, provide as much information as possible. | |
You put a [/CONTENT] at the end of the Content. | |
Do not reply as if you are talking about the slideshow itself. (ex. "Include pictures here about...") | |
Do not include any special characters (?, !, ., :, ) in the Title. | |
Do not include any additional information in your response and stick to the format.""" | |
# response = openai.ChatCompletion.create( | |
# model="gpt-3.5-turbo", | |
# messages=[ | |
# {"role": "user", "content": message} | |
# ] | |
# ) | |
response = openai.ChatCompletion.create( | |
model="gpt-3.5-turbo", | |
messages=[ | |
{ | |
"role": "system", | |
"content": ( | |
"You are a helpful assistant capable of creating clear and concise PowerPoint slide outlines used by teachers during their lessons based on a given lesson plan." | |
), | |
}, | |
{"role": "user", "content": message}, | |
], | |
max_tokens=2000, | |
n=1, | |
stop=None, | |
temperature=0.7, | |
# top_p=0.9, | |
) | |
# """ Ref for slide types: | |
# 0 -> title and subtitle | |
# 1 -> title and content | |
# 2 -> section header | |
# 3 -> two content | |
# 4 -> Comparison | |
# 5 -> Title only | |
# 6 -> Blank | |
# 7 -> Content with caption | |
# 8 -> Pic with caption | |
# """ | |
def delete_all_slides(): | |
for i in range(len(root.slides) - 1, -1, -1): | |
r_id = root.slides._sldIdLst[i].rId | |
root.part.drop_rel(r_id) | |
del root.slides._sldIdLst[i] | |
def create_title_slide(title, subtitle): | |
layout = root.slide_layouts[0] | |
slide = root.slides.add_slide(layout) | |
slide.shapes.title.text = title | |
slide.placeholders[1].text = subtitle | |
def create_section_header_slide(title): | |
layout = root.slide_layouts[2] | |
slide = root.slides.add_slide(layout) | |
slide.shapes.title.text = title | |
def create_title_and_content_slide(title, content): | |
layout = root.slide_layouts[1] | |
slide = root.slides.add_slide(layout) | |
slide.shapes.title.text = title | |
slide.placeholders[1].text = content | |
def create_title_and_content_and_image_slide(title, content, image_query): | |
layout = root.slide_layouts[8] | |
slide = root.slides.add_slide(layout) | |
slide.shapes.title.text = title | |
slide.placeholders[2].text = content | |
refresh_bad_coding_practice() | |
bing_crawler = GoogleImageCrawler(downloader_cls=PrefixNameDownloader, storage={'root_dir': os.getcwd()}) | |
bing_crawler.crawl(keyword=image_query, max_num=1) | |
dir_path = os.path.dirname(os.path.realpath(__file__)) | |
file_name = glob.glob(f"prefix_{bad_coding_practice}*") | |
print(file_name) | |
img_path = os.path.join(dir_path, file_name[0]) | |
slide.shapes.add_picture(img_path, slide.placeholders[1].left, slide.placeholders[1].top, | |
slide.placeholders[1].width, slide.placeholders[1].height) | |
def find_text_in_between_tags(text, start_tag, end_tag): | |
start_pos = text.find(start_tag) | |
end_pos = text.find(end_tag) | |
result = [] | |
while start_pos > -1 and end_pos > -1: | |
text_between_tags = text[start_pos + len(start_tag):end_pos] | |
result.append(text_between_tags) | |
start_pos = text.find(start_tag, end_pos + len(end_tag)) | |
end_pos = text.find(end_tag, start_pos) | |
res1 = "".join(result) | |
res2 = re.sub(r"\[IMAGE\].*?\[/IMAGE\]", '', res1) | |
if len(result) > 0: | |
return res2 | |
else: | |
return "" | |
def search_for_slide_type(text): | |
tags = ["[L_TS]", "[L_CS]", "[L_IS]", "[L_THS]"] | |
found_text = next((s for s in tags if s in text), None) | |
return found_text | |
def parse_response(reply): | |
list_of_slides = reply.split("[SLIDEBREAK]") | |
for slide in list_of_slides: | |
slide_type = search_for_slide_type(slide) | |
if slide_type == "[L_TS]": | |
create_title_slide(find_text_in_between_tags(str(slide), "[TITLE]", "[/TITLE]"), | |
find_text_in_between_tags(str(slide), "[SUBTITLE]", "[/SUBTITLE]")) | |
elif slide_type == "[L_CS]": | |
create_title_and_content_slide("".join(find_text_in_between_tags(str(slide), "[TITLE]", "[/TITLE]")), | |
"".join(find_text_in_between_tags(str(slide), "[CONTENT]", | |
"[/CONTENT]"))) | |
elif slide_type == "[L_IS]": | |
create_title_and_content_and_image_slide("".join(find_text_in_between_tags(str(slide), "[TITLE]", | |
"[/TITLE]")), | |
"".join(find_text_in_between_tags(str(slide), "[CONTENT]", | |
"[/CONTENT]")), | |
"".join(find_text_in_between_tags(str(slide), "[IMAGE]", | |
"[/IMAGE]"))) | |
elif slide_type == "[L_THS]": | |
create_section_header_slide("".join(find_text_in_between_tags(str(slide), "[TITLE]", "[/TITLE]"))) | |
def find_title(): | |
return root.slides[0].shapes.title.text | |
delete_all_slides() | |
print(response) | |
parse_response(response['choices'][0]['message']['content']) | |
name_ = str(uuid4()).replace('-', '') | |
root.save(f"./{name_}.pptx") | |
print("done") | |
dir_path = "./" | |
prefix = "prefix_" | |
for file_name in os.listdir(dir_path): | |
if file_name.startswith(prefix): | |
file_path = os.path.join(dir_path, file_name) | |
if os.path.isfile(file_path): | |
os.remove(file_path) | |
return f"./{name_}.pptx" | |
with gr.Blocks(title="AI Generated Presentation") as demo: | |
gr.Markdown("""<h1><center>AI Generated Presentation</center></h1>""") | |
with gr. Row(): | |
with gr. Column(): | |
openai_token = gr. Textbox(label="OpenAI API Key", type='password') | |
topic = gr.Textbox(label="Topic of the presentation") | |
length = gr.Slider(minimum=1, maximum=50, value=6, label="number of generated PPT pages", step=1) | |
theme = gr.File(value="./theme.pptx", file_types=['pptx', 'ppt'], label="PPT template") | |
output_file = gr. File(interactive=False) | |
topic. submit( | |
fn=generate_ppt, | |
inputs=[theme, topic, length, openai_token], | |
outputs=[output_file] | |
) | |
submit = gr.Button("generate") | |
submit. click( | |
fn=generate_ppt, | |
inputs=[theme, topic, length, openai_token], | |
outputs=[output_file] | |
) | |
if __name__ == "__main__": | |
demo.launch() | |