DavidFernandes commited on
Commit
734b424
·
verified ·
1 Parent(s): a1b400b

Upload 3 files

Browse files
Files changed (3) hide show
  1. app.py +266 -0
  2. requirements.txt +4 -0
  3. theme.pptx +0 -0
app.py ADDED
@@ -0,0 +1,266 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import glob
2
+ import os
3
+ import random
4
+ import re
5
+ import string
6
+
7
+ import gradio as gr
8
+
9
+ import openai
10
+ from icrawler import ImageDownloader
11
+ from icrawler.builtin import GoogleImageCrawler, BingImageCrawler
12
+ from uuid import uuid4
13
+ from pptx import Presentation
14
+
15
+ bad_coding_practice = ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in
16
+ range(16))
17
+
18
+
19
+ def refresh_bad_coding_practice():
20
+ global bad_coding_practice
21
+ bad_coding_practice = ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits)
22
+ for _ in range(16))
23
+ return
24
+
25
+
26
+ class PrefixNameDownloader(ImageDownloader):
27
+
28
+ def get_filename(self, task, default_ext):
29
+ filename = super(PrefixNameDownloader, self).get_filename(
30
+ task, default_ext)
31
+ print(bad_coding_practice)
32
+ return 'prefix_' + bad_coding_practice + filename
33
+
34
+
35
+ def generate_ppt(file, topic, slide_length, api_key):
36
+ print(file.name)
37
+
38
+ root = Presentation(file.name)
39
+
40
+ openai.api_key = api_key
41
+
42
+ message = f"""
43
+ Create content for a slideshow presentation.
44
+ The content's topic is {topic}.
45
+ The slideshow is {slide_length} slides long.
46
+ The content is written in the language of the content I give you above.
47
+
48
+
49
+ You are allowed to use the following slide types:
50
+
51
+ Slide types:
52
+ Title Slide - (Title, Subtitle)
53
+ Content Slide - (Title, Content)
54
+ Image Slide - (Title, Content, Image)
55
+ Thanks Slide - (Title)
56
+
57
+ Put this tag before the Title Slide: [L_TS]
58
+ Put this tag before the Content Slide: [L_CS]
59
+ Put this tag before the Image Slide: [L_IS]
60
+ Put this tag before the Thanks Slide: [L_THS]
61
+
62
+ Put "[SLIDEBREAK]" after each slide
63
+
64
+ For example:
65
+ [L_TS]
66
+ [TITLE]Mental Health[/TITLE]
67
+
68
+ [SLIDEBREAK]
69
+
70
+ [L_CS]
71
+ [TITLE]Mental Health Definition[/TITLE]
72
+ [CONTENT]
73
+ 1. Definition: A person’s condition with regard to their psychological and emotional well-being
74
+ 2. Can impact one's physical health
75
+ 3. Stigmatized too often.
76
+ [/CONTENT]
77
+
78
+ [SLIDEBREAK]
79
+
80
+ Put this tag before the Title: [TITLE]
81
+ Put this tag after the Title: [/TITLE]
82
+ Put this tag before the Subitle: [SUBTITLE]
83
+ Put this tag after the Subtitle: [/SUBTITLE]
84
+ Put this tag before the Content: [CONTENT]
85
+ Put this tag after the Content: [/CONTENT]
86
+ Put this tag before the Image: [IMAGE]
87
+ Put this tag after the Image: [/IMAGE]
88
+
89
+ Elaborate on the Content, provide as much information as possible.
90
+ You put a [/CONTENT] at the end of the Content.
91
+ Do not reply as if you are talking about the slideshow itself. (ex. "Include pictures here about...")
92
+ Do not include any special characters (?, !, ., :, ) in the Title.
93
+ Do not include any additional information in your response and stick to the format."""
94
+
95
+ # response = openai.ChatCompletion.create(
96
+ # model="gpt-3.5-turbo",
97
+ # messages=[
98
+ # {"role": "user", "content": message}
99
+ # ]
100
+ # )
101
+
102
+ response = openai.ChatCompletion.create(
103
+ model="gpt-3.5-turbo",
104
+ messages=[
105
+ {
106
+ "role": "system",
107
+ "content": (
108
+ "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."
109
+ ),
110
+ },
111
+ {"role": "user", "content": message},
112
+ ],
113
+ max_tokens=2000,
114
+ n=1,
115
+ stop=None,
116
+ temperature=0.7,
117
+ # top_p=0.9,
118
+ )
119
+
120
+ # """ Ref for slide types:
121
+ # 0 -> title and subtitle
122
+ # 1 -> title and content
123
+ # 2 -> section header
124
+ # 3 -> two content
125
+ # 4 -> Comparison
126
+ # 5 -> Title only
127
+ # 6 -> Blank
128
+ # 7 -> Content with caption
129
+ # 8 -> Pic with caption
130
+ # """
131
+
132
+ def delete_all_slides():
133
+ for i in range(len(root.slides) - 1, -1, -1):
134
+ r_id = root.slides._sldIdLst[i].rId
135
+ root.part.drop_rel(r_id)
136
+ del root.slides._sldIdLst[i]
137
+
138
+ def create_title_slide(title, subtitle):
139
+ layout = root.slide_layouts[0]
140
+ slide = root.slides.add_slide(layout)
141
+ slide.shapes.title.text = title
142
+ slide.placeholders[1].text = subtitle
143
+
144
+ def create_section_header_slide(title):
145
+ layout = root.slide_layouts[2]
146
+ slide = root.slides.add_slide(layout)
147
+ slide.shapes.title.text = title
148
+
149
+ def create_title_and_content_slide(title, content):
150
+ layout = root.slide_layouts[1]
151
+ slide = root.slides.add_slide(layout)
152
+ slide.shapes.title.text = title
153
+ slide.placeholders[1].text = content
154
+
155
+ def create_title_and_content_and_image_slide(title, content, image_query):
156
+ layout = root.slide_layouts[8]
157
+ slide = root.slides.add_slide(layout)
158
+ slide.shapes.title.text = title
159
+ slide.placeholders[2].text = content
160
+ refresh_bad_coding_practice()
161
+ bing_crawler = GoogleImageCrawler(downloader_cls=PrefixNameDownloader, storage={'root_dir': os.getcwd()})
162
+ bing_crawler.crawl(keyword=image_query, max_num=1)
163
+ dir_path = os.path.dirname(os.path.realpath(__file__))
164
+ file_name = glob.glob(f"prefix_{bad_coding_practice}*")
165
+ print(file_name)
166
+ img_path = os.path.join(dir_path, file_name[0])
167
+ slide.shapes.add_picture(img_path, slide.placeholders[1].left, slide.placeholders[1].top,
168
+ slide.placeholders[1].width, slide.placeholders[1].height)
169
+
170
+ def find_text_in_between_tags(text, start_tag, end_tag):
171
+ start_pos = text.find(start_tag)
172
+ end_pos = text.find(end_tag)
173
+ result = []
174
+ while start_pos > -1 and end_pos > -1:
175
+ text_between_tags = text[start_pos + len(start_tag):end_pos]
176
+ result.append(text_between_tags)
177
+ start_pos = text.find(start_tag, end_pos + len(end_tag))
178
+ end_pos = text.find(end_tag, start_pos)
179
+ res1 = "".join(result)
180
+ res2 = re.sub(r"\[IMAGE\].*?\[/IMAGE\]", '', res1)
181
+ if len(result) > 0:
182
+ return res2
183
+ else:
184
+ return ""
185
+
186
+ def search_for_slide_type(text):
187
+ tags = ["[L_TS]", "[L_CS]", "[L_IS]", "[L_THS]"]
188
+ found_text = next((s for s in tags if s in text), None)
189
+ return found_text
190
+
191
+ def parse_response(reply):
192
+ list_of_slides = reply.split("[SLIDEBREAK]")
193
+ for slide in list_of_slides:
194
+ slide_type = search_for_slide_type(slide)
195
+ if slide_type == "[L_TS]":
196
+ create_title_slide(find_text_in_between_tags(str(slide), "[TITLE]", "[/TITLE]"),
197
+ find_text_in_between_tags(str(slide), "[SUBTITLE]", "[/SUBTITLE]"))
198
+ elif slide_type == "[L_CS]":
199
+ create_title_and_content_slide("".join(find_text_in_between_tags(str(slide), "[TITLE]", "[/TITLE]")),
200
+ "".join(find_text_in_between_tags(str(slide), "[CONTENT]",
201
+ "[/CONTENT]")))
202
+ elif slide_type == "[L_IS]":
203
+ create_title_and_content_and_image_slide("".join(find_text_in_between_tags(str(slide), "[TITLE]",
204
+ "[/TITLE]")),
205
+ "".join(find_text_in_between_tags(str(slide), "[CONTENT]",
206
+ "[/CONTENT]")),
207
+ "".join(find_text_in_between_tags(str(slide), "[IMAGE]",
208
+ "[/IMAGE]")))
209
+ elif slide_type == "[L_THS]":
210
+ create_section_header_slide("".join(find_text_in_between_tags(str(slide), "[TITLE]", "[/TITLE]")))
211
+
212
+ def find_title():
213
+ return root.slides[0].shapes.title.text
214
+
215
+ delete_all_slides()
216
+
217
+ print(response)
218
+
219
+ parse_response(response['choices'][0]['message']['content'])
220
+
221
+ name_ = str(uuid4()).replace('-', '')
222
+
223
+ root.save(f"./{name_}.pptx")
224
+
225
+ print("done")
226
+
227
+ dir_path = "./"
228
+ prefix = "prefix_"
229
+
230
+ for file_name in os.listdir(dir_path):
231
+ if file_name.startswith(prefix):
232
+ file_path = os.path.join(dir_path, file_name)
233
+ if os.path.isfile(file_path):
234
+ os.remove(file_path)
235
+
236
+ return f"./{name_}.pptx"
237
+
238
+
239
+ with gr.Blocks(title="AI Generated Presentation") as demo:
240
+ gr.Markdown("""<h1><center>AI Generated Presentation</center></h1>""")
241
+ with gr. Row():
242
+ with gr. Column():
243
+ openai_token = gr. Textbox(label="OpenAI API Key", type='password')
244
+ topic = gr.Textbox(label="Topic of the presentation")
245
+ length = gr.Slider(minimum=1, maximum=50, value=6, label="number of generated PPT pages", step=1)
246
+ theme = gr.File(value="./theme.pptx", file_types=['pptx', 'ppt'], label="PPT template")
247
+ output_file = gr. File(interactive=False)
248
+
249
+ topic. submit(
250
+ fn=generate_ppt,
251
+ inputs=[theme, topic, length, openai_token],
252
+ outputs=[output_file]
253
+ )
254
+
255
+ submit = gr.Button("generate")
256
+ submit. click(
257
+ fn=generate_ppt,
258
+ inputs=[theme, topic, length, openai_token],
259
+ outputs=[output_file]
260
+ )
261
+
262
+
263
+
264
+
265
+ if __name__ == "__main__":
266
+ demo.launch()
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ gradio==3.21.0
2
+ python-pptx==0.6.21
3
+ icrawler==0.6.6
4
+ openai==0.27.1
theme.pptx ADDED
Binary file (181 kB). View file