ash2203 commited on
Commit
ee87229
·
verified ·
1 Parent(s): 9afd61b

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +218 -0
app.py ADDED
@@ -0,0 +1,218 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from pptx import Presentation
3
+ from pptx.util import Inches, Pt
4
+ from pptx.dml.color import RGBColor
5
+ from pptx.enum.text import PP_ALIGN
6
+ from groq import Groq
7
+ import os
8
+ import json
9
+ from dotenv import load_dotenv
10
+ import tempfile
11
+ from tenacity import retry, stop_after_attempt, wait_fixed
12
+ import random
13
+
14
+ load_dotenv()
15
+
16
+ # Color palettes inspired by Shutterstock
17
+ COLOR_PALETTES = [
18
+ {
19
+ 'primary': RGBColor(255, 87, 51), # Orange
20
+ 'secondary': RGBColor(0, 115, 207), # Blue
21
+ 'accent': RGBColor(255, 255, 255), # White
22
+ 'text': RGBColor(51, 51, 51), # Dark Gray
23
+ 'background': RGBColor(242, 242, 242) # Light Gray
24
+ },
25
+ {
26
+ 'primary': RGBColor(102, 45, 145), # Purple
27
+ 'secondary': RGBColor(255, 230, 0), # Yellow
28
+ 'accent': RGBColor(0, 255, 255), # Cyan
29
+ 'text': RGBColor(51, 51, 51), # Dark Gray
30
+ 'background': RGBColor(230, 230, 250) # Lavender
31
+ },
32
+ {
33
+ 'primary': RGBColor(0, 176, 80), # Green
34
+ 'secondary': RGBColor(255, 192, 0), # Gold
35
+ 'accent': RGBColor(0, 112, 192), # Blue
36
+ 'text': RGBColor(51, 51, 51), # Dark Gray
37
+ 'background': RGBColor(240, 255, 240) # Honeydew
38
+ },
39
+ {
40
+ 'primary': RGBColor(192, 0, 0), # Red
41
+ 'secondary': RGBColor(0, 176, 240), # Light Blue
42
+ 'accent': RGBColor(255, 255, 255), # White
43
+ 'text': RGBColor(51, 51, 51), # Dark Gray
44
+ 'background': RGBColor(255, 240, 245) # Lavender Blush
45
+ },
46
+ {
47
+ 'primary': RGBColor(0, 80, 115), # Dark Blue
48
+ 'secondary': RGBColor(255, 140, 0), # Dark Orange
49
+ 'accent': RGBColor(0, 176, 80), # Green
50
+ 'text': RGBColor(51, 51, 51), # Dark Gray
51
+ 'background': RGBColor(240, 248, 255) # Alice Blue
52
+ }
53
+ ]
54
+
55
+ def get_random_color_palette():
56
+ return random.choice(COLOR_PALETTES)
57
+
58
+ def apply_theme(prs, color_scheme):
59
+ # Apply theme colors to the master slide
60
+ background = prs.slide_masters[0].background
61
+ background.fill.solid()
62
+ background.fill.fore_color.rgb = color_scheme['background']
63
+
64
+ # Apply theme colors to placeholders
65
+ for shape in prs.slide_masters[0].placeholders:
66
+ if shape.has_text_frame:
67
+ for paragraph in shape.text_frame.paragraphs:
68
+ for run in paragraph.runs:
69
+ run.font.color.rgb = color_scheme['text']
70
+
71
+ def create_title_slide(prs, title, color_scheme):
72
+ slide_layout = prs.slide_layouts[0] # Title Slide layout
73
+ slide = prs.slides.add_slide(slide_layout)
74
+
75
+ title_shape = slide.shapes.title
76
+ subtitle_shape = slide.placeholders[1]
77
+
78
+ title_shape.text = title
79
+ title_shape.text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER
80
+ title_shape.text_frame.paragraphs[0].font.color.rgb = color_scheme['primary']
81
+ title_shape.text_frame.paragraphs[0].font.size = Pt(44)
82
+
83
+ subtitle_shape.text = "Generated with AI"
84
+ subtitle_shape.text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER
85
+ subtitle_shape.text_frame.paragraphs[0].font.color.rgb = color_scheme['secondary']
86
+ subtitle_shape.text_frame.paragraphs[0].font.size = Pt(24)
87
+
88
+ def create_content_slide(prs, title, content, color_scheme):
89
+ slide_layout = prs.slide_layouts[1] # Content with Caption layout
90
+ slide = prs.slides.add_slide(slide_layout)
91
+
92
+ title_shape = slide.shapes.title
93
+ title_shape.text = title
94
+ title_shape.text_frame.paragraphs[0].font.color.rgb = color_scheme['primary']
95
+ title_shape.text_frame.paragraphs[0].font.size = Pt(36)
96
+
97
+ content_shape = slide.placeholders[1]
98
+ tf = content_shape.text_frame
99
+ tf.clear() # Clear existing text
100
+
101
+ # Add main content
102
+ p = tf.paragraphs[0]
103
+ p.text = content['main']
104
+ p.font.size = Pt(18)
105
+ p.font.color.rgb = color_scheme['text']
106
+
107
+ # Add bullet points
108
+ for bullet in content['bullets']:
109
+ p = tf.add_paragraph()
110
+ p.text = bullet
111
+ p.level = 1
112
+ p.font.size = Pt(16)
113
+ p.font.color.rgb = color_scheme['text']
114
+
115
+ # Add a subtle accent to the slide
116
+ left = Inches(0)
117
+ top = Inches(6.5)
118
+ width = prs.slide_width
119
+ height = Inches(0.5)
120
+ shape = slide.shapes.add_shape(1, left, top, width, height)
121
+ shape.fill.solid()
122
+ shape.fill.fore_color.rgb = color_scheme['accent']
123
+ shape.line.color.rgb = color_scheme['accent']
124
+
125
+ @retry(stop=stop_after_attempt(5), wait=wait_fixed(2))
126
+ def generate_slides_content(user_input, num_slides):
127
+ client = Groq(api_key=os.getenv("GROQ_API_KEY"))
128
+
129
+ prompt = f"""
130
+ Based on the following input, generate a PowerPoint presentation structure with exactly {num_slides} slides.
131
+ The output should be a JSON array of slides, where each slide is an object with a 'title', 'main' content, and 'bullets' (an array of bullet points).
132
+ Make sure the content is concise and suitable for a presentation.
133
+
134
+ User Input: {user_input}
135
+
136
+ Example output format:
137
+ [
138
+ {{
139
+ "title": "Slide Title",
140
+ "main": "Main content of the slide",
141
+ "bullets": ["Bullet point 1", "Bullet point 2", "Bullet point 3"]
142
+ }},
143
+ // ... more slides (total should be {num_slides})
144
+ ]
145
+ """
146
+
147
+ try:
148
+ chat_completion = client.chat.completions.create(
149
+ messages=[
150
+ {"role": "system", "content": "You are a helpful assistant that generates PowerPoint presentation content and return the content in JSON format."},
151
+ {"role": "user", "content": prompt}
152
+ ],
153
+ model="mixtral-8x7b-32768",
154
+ temperature=1,
155
+ max_tokens=3000
156
+ )
157
+
158
+ return json.loads(chat_completion.choices[0].message.content)
159
+ except json.JSONDecodeError:
160
+ st.error("Error: Invalid JSON response from the AI. Retrying...")
161
+ raise
162
+ except Exception as e:
163
+ st.error(f"An error occurred: {str(e)}. Retrying...")
164
+ raise
165
+
166
+ def generate_presentation(user_input, num_slides):
167
+ try:
168
+ slides_content = generate_slides_content(user_input, num_slides)
169
+
170
+ prs = Presentation()
171
+ color_scheme = get_random_color_palette()
172
+ apply_theme(prs, color_scheme)
173
+
174
+ # Create title slide
175
+ create_title_slide(prs, slides_content[0]['title'], color_scheme)
176
+
177
+ # Create content slides
178
+ for slide in slides_content[1:]: # Skip the first slide as it's used for the title
179
+ create_content_slide(prs, slide['title'], {'main': slide['main'], 'bullets': slide['bullets']}, color_scheme)
180
+
181
+ with tempfile.NamedTemporaryFile(delete=False, suffix='.pptx') as tmp:
182
+ prs.save(tmp.name)
183
+ return tmp.name
184
+ except Exception as e:
185
+ st.error(f"Failed to generate presentation: {str(e)}")
186
+ return None
187
+
188
+ def main():
189
+ st.set_page_config(page_title="PowerPoint Generator", page_icon="📊", layout="wide")
190
+
191
+ st.title("🎨 AI-Powered PowerPoint Generator")
192
+ st.write("Enter your presentation idea and the number of slides you want, and we'll generate a stylish PowerPoint for you!")
193
+
194
+ user_input = st.text_area("Enter the content idea for your presentation:", height=150)
195
+ num_slides = st.number_input("Number of slides:", min_value=2, max_value=20, value=5)
196
+
197
+ if st.button("Generate Presentation", use_container_width=True, type="primary"):
198
+ if user_input and num_slides:
199
+ with st.spinner("Generating your stylish presentation... This may take a moment."):
200
+ ppt_file = generate_presentation(user_input, num_slides)
201
+
202
+ if ppt_file:
203
+ st.success("Presentation generated successfully!")
204
+
205
+ with open(ppt_file, "rb") as file:
206
+ st.download_button(
207
+ label="Download PowerPoint",
208
+ data=file,
209
+ file_name="generated_presentation.pptx",
210
+ mime="application/vnd.openxmlformats-officedocument.presentationml.presentation"
211
+ )
212
+ else:
213
+ st.error("Failed to generate the presentation. Please try again.")
214
+ else:
215
+ st.warning("Please enter content and specify the number of slides (minimum 2).")
216
+
217
+ if __name__ == "__main__":
218
+ main()