File size: 7,547 Bytes
0e9775d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84c338e
0e9775d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d7cbd17
0e9775d
d7cbd17
0e9775d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3aa5564
 
 
 
 
 
 
 
 
 
0e9775d
 
3aa5564
 
0e9775d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79a9bd7
 
 
 
 
 
 
 
 
0e9775d
7d5d846
0e9775d
 
7d5d846
0e9775d
 
 
 
 
 
 
 
3aa5564
 
0e9775d
 
 
 
 
 
 
 
 
 
3aa5564
0e9775d
 
 
 
 
9332cd4
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
import gradio as gr
import os
import openai
import subprocess
import base64

def encode_image(image_path):
    with open(image_path, 'rb') as image_file:
        return base64.b64encode(image_file.read()).decode('utf-8')

def extract_code_pieces(text: str, concat: bool = True) -> list[str]:
    """Extract code pieces from a text string.
    Args:
        text: str, model prediciton text.
    Rets:
        code_pieces: list[str], code pieces in the text.
    """
    code_pieces = []
    while "```python" in text:
        st_idx = text.index("```python") + 10
        # end_idx = text.index("```", st_idx)
        if "```" in text[st_idx:]:
            end_idx = text.index("```", st_idx)
        else: 
            end_idx = len(text)
        code_pieces.append(text[st_idx:end_idx].strip())
        text = text[end_idx+3:].strip()
    if concat: return '\n\n'.join(code_pieces)
    return code_pieces

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:
1.  Ensure your code can successfully execute. If needed, you can also write tests to verify your code.
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.
3. Carefully select the colors of text, shapes, and backgrounds, to ensure all contents are readable.
4. The slides should not look empty or incomplete. When filling the content in the slides, maintain good design and layout."""

# INSTRUCTION = """Follow the instruction below to create the slide. 
# If the instruction is long and specific, follow the instruction carefully and add all elements as required; 
# if it is short and concise, you will need to create some content (text, image, layout) and implement it into the slide.
# {}

# Finally, your code should save the pptx file to path "{}"."""
with open('agent_no_image_new_lib.prompt', 'r') as f:
    INSTRUCTION = f.read()

import glob
import time

def list_files_in_directory(directory):
    """Lists all files in the given directory."""
    return set(glob.glob(os.path.join(directory, "*")))

def cleanup_temp_files(temp_files):
    """Deletes a list of temporary files if they exist."""
    for temp_file in temp_files:
        try:
            if os.path.exists(temp_file):
                os.remove(temp_file)
                print(f"Deleted temporary file: {temp_file}")
        except Exception as e:
            print(f"Failed to delete {temp_file}: {e}")


def create_pptx(api_key, instruction, model_name="gpt-4o", max_tokens=4096):
    try:
        # Set OpenAI API key
        openai.api_key = api_key

        # Create OpenAI client
        client = openai.OpenAI(api_key=api_key)

        # Prepare messages for the chat completion
        messages = [{"role": "system", "content": SYSTEM_MESSAGE}]
        pptx_path = "output.pptx"
        instruction_message = INSTRUCTION.replace("INSERT_INSTRUCTION_HERE", instruction)
        messages.append({"role": "user", "content": instruction_message})
        # Capture the directory state before execution
        working_directory = os.getcwd()
        files_before = list_files_in_directory(working_directory)
        # Retry up to 3 times
        for attempt in range(3):
            try:
                # Call OpenAI's GPT model
                response = client.chat.completions.create(
                    model=model_name,
                    messages=messages,
                    max_tokens=max_tokens,
                    n=1,
                )
                generated_code = extract_code_pieces(response.choices[0].message.content, concat=True)
                generated_code = generated_code.replace("from library import", "from SlidesLib import")
                generated_code = generated_code.replace("generate_image(", f"generate_image({repr(api_key)},")
                generated_code = "from SlidesLib import *\n\n" + generated_code

                # Save the generated code
                code_file = "generated_slide_code.py"
                with open(code_file, "w") as f:
                    f.write(generated_code)

                # Execute the generated code
                result = subprocess.run(["python", code_file], capture_output=True, text=True, check=True)
                print(result.stdout)
                
                # Capture the directory state after execution
                files_after = list_files_in_directory(working_directory)
                temp_files = files_after - files_before  # Identify newly created files

                # Convert the pptx to jpg for preview
                # preview_image = "image_previews/output.jpg"
                # command = [
                #     "libreoffice",
                #     "--headless",
                #     "--convert-to", "jpg",
                #     "--outdir", "image_previews",
                #     pptx_path
                # ]
                # subprocess.run(command)
                # temp_files.add(preview_image) 

                # If successful, return the result
                return "Slide generated successfully! Download your slide below.", pptx_path
                # , preview_image
            except subprocess.CalledProcessError as e:
                print(f"Attempt {attempt + 1} failed: {e.stderr}")

        # Fallback: Use default code if all attempts fail
        print("All 3 attempts failed. Running default code.")
        default_code = f"""
from pptx import Presentation

ppt = Presentation()
slide = ppt.slides.add_slide(ppt.slide_layouts[5])
title = slide.shapes.title
title.text = "Insert Title Here"

content = slide.placeholders[0]
content.text = "{instruction}"

ppt.save("output.pptx")
"""
        code_file = "default_slide_code.py"
        with open(code_file, "w") as f:
            f.write(default_code)
        
        # Execute the default code
        subprocess.run(["python", code_file], capture_output=True, text=True, check=True)

        # Convert the pptx to jpg for preview
        # preview_image = "image_previews/output.jpg"
        # command = [
        #     "libreoffice",
        #     "--headless",
        #     "--convert-to", "jpg",
        #     "--outdir", "image_previews",
        #     pptx_path
        # ]
        # subprocess.run(command)

        return "Default slide generated after 3 attempts failed.", pptx_path

    except Exception as e:
        return f"An error occurred: {str(e)}", None
    finally:
        # Cleanup temporary files
        files_before.add("output.pptx")
        temp_files = list_files_in_directory(working_directory) - files_before
        cleanup_temp_files(temp_files)

# Create a Gradio interface
def gradio_demo(api_key, instruction):
    status, pptx_path = create_pptx(api_key, instruction)
    return status, pptx_path

iface = gr.Interface(
    fn=gradio_demo,
    inputs=[
        gr.Textbox(label="OpenAI API Key", type="password"),
        gr.Textbox(label="Instruction", placeholder="Enter your slide instruction here...")
    ],
    outputs=[
        gr.Textbox(label="Status"),
        gr.File(label="Download Slide"),
        # gr.Image(label="Slide Preview", type="filepath")
    ],
    title="AutoPresent",
    description="Automatically Generate a presentation slide"
)

iface.launch()