para-lost commited on
Commit
0e9775d
·
1 Parent(s): 16160c0
Files changed (1) hide show
  1. app.py +189 -0
app.py ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import os
3
+ import openai
4
+ import subprocess
5
+ import base64
6
+
7
+ def encode_image(image_path):
8
+ with open(image_path, 'rb') as image_file:
9
+ return base64.b64encode(image_file.read()).decode('utf-8')
10
+
11
+ def extract_code_pieces(text: str, concat: bool = True) -> list[str]:
12
+ """Extract code pieces from a text string.
13
+ Args:
14
+ text: str, model prediciton text.
15
+ Rets:
16
+ code_pieces: list[str], code pieces in the text.
17
+ """
18
+ code_pieces = []
19
+ while "```python" in text:
20
+ st_idx = text.index("```python") + 10
21
+ # end_idx = text.index("```", st_idx)
22
+ if "```" in text[st_idx:]:
23
+ end_idx = text.index("```", st_idx)
24
+ else:
25
+ end_idx = len(text)
26
+ code_pieces.append(text[st_idx:end_idx].strip())
27
+ text = text[end_idx+3:].strip()
28
+ if concat: return '\n\n'.join(code_pieces)
29
+ return code_pieces
30
+
31
+ SYSTEM_MESSAGE = """* You are an expert presentation slides designer who creates modern, fashionable, and stylish slides using Python code. Your job is to generate the required PPTX slide by writing and executing a Python script. Make sure to follow the guidelines below and do not skip any of them:
32
+ 1. Ensure your code can successfully execute. If needed, you can also write tests to verify your code.
33
+ 2. Maintain proper spacing and arrangements of elements in the slide: make sure to keep sufficient spacing between different elements; do not make elements overlap or overflow to the slide page.
34
+ 3. Carefully select the colors of text, shapes, and backgrounds, to ensure all contents are readable.
35
+ 4. The slides should not look empty or incomplete. When filling the content in the slides, maintain good design and layout."""
36
+
37
+ # INSTRUCTION = """Follow the instruction below to create the slide.
38
+ # If the instruction is long and specific, follow the instruction carefully and add all elements as required;
39
+ # if it is short and concise, you will need to create some content (text, image, layout) and implement it into the slide.
40
+ # {}
41
+
42
+ # Finally, your code should save the pptx file to path "{}"."""
43
+ with open('SlidesAgent/presenter/prompts/agent_no_image_new_lib.prompt', 'r') as f:
44
+ INSTRUCTION = f.read()
45
+
46
+ import glob
47
+ import time
48
+
49
+ def list_files_in_directory(directory):
50
+ """Lists all files in the given directory."""
51
+ return set(glob.glob(os.path.join(directory, "*")))
52
+
53
+ def cleanup_temp_files(temp_files):
54
+ """Deletes a list of temporary files if they exist."""
55
+ for temp_file in temp_files:
56
+ try:
57
+ if os.path.exists(temp_file):
58
+ os.remove(temp_file)
59
+ print(f"Deleted temporary file: {temp_file}")
60
+ except Exception as e:
61
+ print(f"Failed to delete {temp_file}: {e}")
62
+
63
+
64
+ def create_pptx(api_key, instruction, model_name="gpt-4o", max_tokens=4096):
65
+ try:
66
+ # Set OpenAI API key
67
+ openai.api_key = api_key
68
+
69
+ # Create OpenAI client
70
+ client = openai.OpenAI(api_key=api_key)
71
+
72
+ # Prepare messages for the chat completion
73
+ messages = [{"role": "system", "content": SYSTEM_MESSAGE}]
74
+ pptx_path = "output.pptx"
75
+ instruction_message = INSTRUCTION.replace("INSERT_INSTRUCTION_HERE", instruction)
76
+ messages.append({"role": "user", "content": instruction_message})
77
+ # Capture the directory state before execution
78
+ working_directory = os.getcwd()
79
+ files_before = list_files_in_directory(working_directory)
80
+ # Retry up to 3 times
81
+ for attempt in range(3):
82
+ try:
83
+ # Call OpenAI's GPT model
84
+ response = client.chat.completions.create(
85
+ model=model_name,
86
+ messages=messages,
87
+ max_tokens=max_tokens,
88
+ n=1,
89
+ )
90
+ generated_code = extract_code_pieces(response.choices[0].message.content, concat=True)
91
+ generated_code = generated_code.replace("from library import", "from mysearchlib import")
92
+ generated_code = generated_code.replace("generate_image(", f"generate_image({repr(api_key)},")
93
+ generated_code = "from mysearchlib import *\n\n" + generated_code
94
+
95
+ # Save the generated code
96
+ code_file = "generated_slide_code.py"
97
+ with open(code_file, "w") as f:
98
+ f.write(generated_code)
99
+
100
+ # Execute the generated code
101
+ result = subprocess.run(["python", code_file], capture_output=True, text=True, check=True)
102
+ print(result.stdout)
103
+
104
+ # Capture the directory state after execution
105
+ files_after = list_files_in_directory(working_directory)
106
+ temp_files = files_after - files_before # Identify newly created files
107
+
108
+ # Convert the pptx to jpg for preview
109
+ preview_image = "image_previews/output.jpg"
110
+ command = [
111
+ "libreoffice",
112
+ "--headless",
113
+ "--convert-to", "jpg",
114
+ "--outdir", "image_previews",
115
+ pptx_path
116
+ ]
117
+ subprocess.run(command)
118
+ temp_files.add(preview_image)
119
+
120
+ # If successful, return the result
121
+ return "Slide generated successfully! Download your slide below.", pptx_path, preview_image
122
+ except subprocess.CalledProcessError as e:
123
+ print(f"Attempt {attempt + 1} failed: {e.stderr}")
124
+
125
+ # Fallback: Use default code if all attempts fail
126
+ print("All 3 attempts failed. Running default code.")
127
+ default_code = f"""
128
+ from pptx import Presentation
129
+
130
+ ppt = Presentation()
131
+ slide = ppt.slides.add_slide(ppt.slide_layouts[5])
132
+ title = slide.shapes.title
133
+ title.text = "Insert Title Here"
134
+
135
+ content = slide.placeholders[0]
136
+ content.text = "{instruction}"
137
+
138
+ ppt.save("output.pptx")
139
+ """
140
+ code_file = "default_slide_code.py"
141
+ with open(code_file, "w") as f:
142
+ f.write(default_code)
143
+
144
+ # Execute the default code
145
+ subprocess.run(["python", code_file], capture_output=True, text=True, check=True)
146
+
147
+ # Convert the pptx to jpg for preview
148
+ preview_image = "image_previews/output.jpg"
149
+ command = [
150
+ "libreoffice",
151
+ "--headless",
152
+ "--convert-to", "jpg",
153
+ "--outdir", "image_previews",
154
+ pptx_path
155
+ ]
156
+ subprocess.run(command)
157
+
158
+ return "Default slide generated after 3 attempts failed.", pptx_path, preview_image
159
+
160
+ except Exception as e:
161
+ return f"An error occurred: {str(e)}", None, None
162
+ finally:
163
+ # Cleanup temporary files
164
+ files_before.add("output.pptx")
165
+ temp_files = list_files_in_directory(working_directory) - files_before
166
+ cleanup_temp_files(temp_files)
167
+
168
+ # Create a Gradio interface
169
+ def gradio_demo(api_key, instruction):
170
+ status, pptx_path, preview_image = create_pptx(api_key, instruction)
171
+ return status, pptx_path, preview_image
172
+
173
+ iface = gr.Interface(
174
+ fn=gradio_demo,
175
+ inputs=[
176
+ gr.Textbox(label="OpenAI API Key", type="password"),
177
+ gr.Textbox(label="Instruction", placeholder="Enter your slide instruction here...")
178
+ ],
179
+ outputs=[
180
+ gr.Textbox(label="Status"),
181
+ gr.File(label="Download Slide"),
182
+ gr.Image(label="Slide Preview", type="filepath")
183
+ ],
184
+ title="AutoPresent",
185
+ description="Automatically Generate a presentation slide"
186
+ )
187
+
188
+ if __name__ == "__main__":
189
+ iface.launch(share=True)