Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,278 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import time
|
3 |
+
import random # To simulate variations like seed
|
4 |
+
|
5 |
+
# --- Placeholder Function (Will Contain Your AI Logic Later) ---
|
6 |
+
def process_prompt_and_generate(user_prompt, image_resolution, guidance_scale, seed, animation_frames, animation_style):
|
7 |
+
"""
|
8 |
+
This function simulates the AI pipeline. It accepts more parameters now.
|
9 |
+
It yields updates for the status and logs.
|
10 |
+
"""
|
11 |
+
logs = []
|
12 |
+
status = "Starting processing..."
|
13 |
+
yield user_prompt, "", None, None, "", "", "", "", "", "\n".join(logs), status # Initial state
|
14 |
+
|
15 |
+
if not user_prompt:
|
16 |
+
logs.append("Error: No prompt provided.")
|
17 |
+
status = "Error: No prompt provided."
|
18 |
+
yield user_prompt, "", None, None, "", "", "", "", "", "\n".join(logs), status
|
19 |
+
return
|
20 |
+
|
21 |
+
# --- Simulate Prompt Enhancement ---
|
22 |
+
status = "Enhancing prompt..."
|
23 |
+
logs.append(f"User Prompt: '{user_prompt}'")
|
24 |
+
logs.append(f"Parameters: Resolution={image_resolution}, Guidance Scale={guidance_scale}, Seed={seed}, Frames={animation_frames}, Style={animation_style}")
|
25 |
+
yield user_prompt, "", None, None, "", "", "", "", "", "\n".join(logs), status
|
26 |
+
time.sleep(1.5) # Simulate time
|
27 |
+
|
28 |
+
enhanced_prompt = f"Stunning, highly detailed, {animation_style.lower()} animation frame of {user_prompt}, cinematic lighting, high focus, 8k, trending on Artstation. Seed: {seed}" # Dummy enhancement
|
29 |
+
logs.append(f"Enhanced Prompt: '{enhanced_prompt}'")
|
30 |
+
yield user_prompt, enhanced_prompt, None, None, "", "", "", "", "", "\n".join(logs), status
|
31 |
+
time.sleep(1) # Simulate time
|
32 |
+
|
33 |
+
# --- Simulate Image Generation ---
|
34 |
+
status = "Generating image..."
|
35 |
+
logs.append(f"Generating initial image ({image_resolution}px)...")
|
36 |
+
yield user_prompt, enhanced_prompt, None, None, "", "", "", "", "", "\n".join(logs), status
|
37 |
+
time.sleep(3) # Simulate time
|
38 |
+
|
39 |
+
# In a real app, this would call a model and return an image path/object
|
40 |
+
dummy_image_path = "https://gradio-app.github.io/assets/tower.jpg" # Example image
|
41 |
+
logs.append(f"Image generated successfully.")
|
42 |
+
yield user_prompt, enhanced_prompt, dummy_image_path, None, "", "", "", "", "", "\n".join(logs), status
|
43 |
+
time.sleep(1)
|
44 |
+
|
45 |
+
# --- Simulate Animation ---
|
46 |
+
status = "Generating animation..."
|
47 |
+
logs.append(f"Generating animation ({animation_frames} frames, style: {animation_style})...")
|
48 |
+
yield user_prompt, enhanced_prompt, dummy_image_path, None, "", "", "", "", "", "\n".join(logs), status
|
49 |
+
time.sleep(4) # Simulate time
|
50 |
+
|
51 |
+
# In a real app, this would call an animation model and return a video path/object
|
52 |
+
dummy_video_path = "https://gradio-app.github.io/assets/video-demo.mp4" # Example video
|
53 |
+
logs.append(f"Animation generated successfully.")
|
54 |
+
yield user_prompt, enhanced_prompt, dummy_image_path, dummy_video_path, "", "", "", "", "", "\n".join(logs), status
|
55 |
+
time.sleep(1)
|
56 |
+
|
57 |
+
# --- Finalizing Outputs ---
|
58 |
+
status = "Process complete!"
|
59 |
+
logs.append("All steps finished.")
|
60 |
+
|
61 |
+
# Prepare metadata string for display
|
62 |
+
metadata = f"Resolution: {image_resolution}px\nGuidance Scale: {guidance_scale}\nSeed: {seed}\nFrames: {animation_frames}\nStyle: {animation_style}"
|
63 |
+
|
64 |
+
|
65 |
+
# The yield statements above sent partial updates. The final return sends the complete data.
|
66 |
+
# However, with generator functions (`yield`), the final result is implicitly what was yielded last.
|
67 |
+
# To ensure all outputs are correctly populated at the end, it's often better to have
|
68 |
+
# the function return the final state once processing is completely done.
|
69 |
+
# Let's refactor slightly to use a single return at the end for simplicity with Gradio's output mapping.
|
70 |
+
# (Alternative: Use gr.Progress and yield intermediary results explicitly)
|
71 |
+
|
72 |
+
# Reset logs for the final return state (or append "Complete")
|
73 |
+
logs.append("Final output ready.")
|
74 |
+
|
75 |
+
return (user_prompt, enhanced_prompt, dummy_image_path, dummy_video_path,
|
76 |
+
str(image_resolution), str(guidance_scale), str(seed), str(animation_frames), animation_style,
|
77 |
+
"\n".join(logs), status)
|
78 |
+
|
79 |
+
|
80 |
+
# --- Gradio UI Definition ---
|
81 |
+
|
82 |
+
# Choose a more modern theme
|
83 |
+
theme = gr.themes.Monochrome().set(
|
84 |
+
# Customize colors slightly for a softer look
|
85 |
+
# You can inspect theme objects and their attributes
|
86 |
+
# button_primary_background_fill="linear-gradient(to right, #6a11cb 0%, #2575fc 100%)", # Example gradient
|
87 |
+
# button_primary_color="white",
|
88 |
+
# button_secondary_background_fill="gray",
|
89 |
+
# spacing_size_lg="2rem" # Example spacing adjustment
|
90 |
+
)
|
91 |
+
|
92 |
+
|
93 |
+
with gr.Blocks(theme=theme, title="AI Creative Studio") as demo:
|
94 |
+
|
95 |
+
# --- Header Section ---
|
96 |
+
with gr.Row(variant="panel"): # Use a panel variant for distinct header background
|
97 |
+
with gr.Column(scale=1, min_width=100):
|
98 |
+
# Placeholder for a logo or icon
|
99 |
+
gr.Image(value="https://gradio-app.github.io/assets/logo.svg",
|
100 |
+
label="Studio Logo",
|
101 |
+
show_label=False, # Hide the label below the image
|
102 |
+
height=80,
|
103 |
+
width=80,
|
104 |
+
container=False) # Prevent adding extra padding/margin around the image
|
105 |
+
|
106 |
+
with gr.Column(scale=4):
|
107 |
+
gr.Markdown(
|
108 |
+
"""
|
109 |
+
# π¨ Multi-Step AI Creative Pipeline π
|
110 |
+
Unleash your imagination! Input a prompt, and our AI orchestrates a sequence:
|
111 |
+
Prompt Enhancement β Image Generation β Animation.
|
112 |
+
"""
|
113 |
+
)
|
114 |
+
gr.Markdown("---") # Separator
|
115 |
+
|
116 |
+
# --- Main Content Area (Input & Output side-by-side initially) ---
|
117 |
+
with gr.Row():
|
118 |
+
|
119 |
+
# --- Input & Controls Column ---
|
120 |
+
with gr.Column(scale=1):
|
121 |
+
gr.Markdown("## βοΈ Your Creative Input")
|
122 |
+
prompt_input = gr.TextArea(
|
123 |
+
label="Enter your prompt here:",
|
124 |
+
placeholder="e.g., A majestic dragon flying over snow-capped mountains at sunset",
|
125 |
+
lines=5,
|
126 |
+
interactive=True
|
127 |
+
)
|
128 |
+
gr.Examples(
|
129 |
+
["A cyberpunk street scene with neon lights", "A cozy cabin in a snowy forest, digital painting", "An astronaut riding a horse on the moon, surrealism"],
|
130 |
+
inputs=prompt_input
|
131 |
+
)
|
132 |
+
|
133 |
+
# Advanced Options (Collapsed)
|
134 |
+
with gr.Accordion("π οΈ Advanced Settings", open=False):
|
135 |
+
gr.Markdown("Configure specific parameters for generation.")
|
136 |
+
|
137 |
+
with gr.Row():
|
138 |
+
image_resolution = gr.Slider(label="Image Resolution (px)", minimum=256, maximum=1024, value=512, step=128, interactive=True)
|
139 |
+
guidance_scale = gr.Slider(label="Guidance Scale", minimum=1.0, maximum=20.0, value=7.0, step=0.1, interactive=True)
|
140 |
+
|
141 |
+
with gr.Row():
|
142 |
+
seed = gr.Number(label="Seed (-1 for random)", value=-1, precision=0, interactive=True)
|
143 |
+
animation_frames = gr.Slider(label="Animation Frames", minimum=10, maximum=100, value=40, step=5, interactive=True)
|
144 |
+
|
145 |
+
animation_style = gr.Radio(
|
146 |
+
label="Animation Style",
|
147 |
+
choices=["Zoom In", "Pan Left", "Rotate", "Swirl"],
|
148 |
+
value="Zoom In",
|
149 |
+
interactive=True
|
150 |
+
)
|
151 |
+
# Add a button to randomize seed easily
|
152 |
+
randomize_seed_button = gr.Button("π² Randomize Seed")
|
153 |
+
|
154 |
+
# Action Button
|
155 |
+
generate_button = gr.Button("β¨ Generate Pipeline Results β¨", variant="primary")
|
156 |
+
|
157 |
+
# Live Status Indicator
|
158 |
+
status_display = gr.Textbox(label="Status", value="Ready", interactive=False, show_copy_button=False)
|
159 |
+
|
160 |
+
|
161 |
+
# --- Output & Results Column ---
|
162 |
+
with gr.Column(scale=2): # Make output column wider
|
163 |
+
gr.Markdown("## β
Generation Results")
|
164 |
+
|
165 |
+
# Row for prompts
|
166 |
+
with gr.Row():
|
167 |
+
original_prompt_output = gr.Textbox(label="Original Prompt Used", interactive=False, lines=3, scale=1, show_copy_button=True)
|
168 |
+
enhanced_prompt_output = gr.Textbox(label="Enhanced Prompt (AI)", interactive=False, lines=3, scale=1, show_copy_button=True)
|
169 |
+
|
170 |
+
# Row for media
|
171 |
+
with gr.Row():
|
172 |
+
generated_image_output = gr.Image(label="Generated Image", interactive=False, height=450, show_share_button=True)
|
173 |
+
generated_animation_output = gr.Video(label="Generated Animation", interactive=False, height=450, show_share_button=True)
|
174 |
+
|
175 |
+
|
176 |
+
# Display Parameters Used (Collapsed or in a smaller section)
|
177 |
+
with gr.Accordion("π¬ Parameters Used", open=False): # Collapsible section for details
|
178 |
+
parameters_used_output = gr.Textbox(
|
179 |
+
label="Generation Parameters",
|
180 |
+
interactive=False,
|
181 |
+
lines=5,
|
182 |
+
show_copy_button=True
|
183 |
+
)
|
184 |
+
# Dummy output components to catch the individual parameters
|
185 |
+
# We will combine them in the process_prompt_and_generate function for the Textbox above
|
186 |
+
res_out = gr.Textbox(visible=False)
|
187 |
+
gs_out = gr.Textbox(visible=False)
|
188 |
+
seed_out = gr.Textbox(visible=False)
|
189 |
+
frames_out = gr.Textbox(visible=False)
|
190 |
+
style_out = gr.Textbox(visible=False)
|
191 |
+
|
192 |
+
|
193 |
+
# Download Buttons (Placeholder)
|
194 |
+
gr.Markdown("### Download Results")
|
195 |
+
with gr.Row():
|
196 |
+
# These buttons are just placeholders for now.
|
197 |
+
# Real download logic needs separate functions.
|
198 |
+
download_image_button = gr.Button("β¬οΈ Download Image", interactive=False) # Make interactive=True when download logic is added
|
199 |
+
download_video_button = gr.Button("β¬οΈ Download Video", interactive=False) # Make interactive=True when download logic is added
|
200 |
+
|
201 |
+
gr.Markdown("---") # Separator
|
202 |
+
|
203 |
+
# --- Logs and Debug Information ---
|
204 |
+
with gr.Accordion("βοΈ Processing Logs & Debug Info", open=False):
|
205 |
+
logs_output = gr.Textbox(
|
206 |
+
label="Detailed Logs",
|
207 |
+
interactive=False,
|
208 |
+
lines=15, # More lines for detailed logs
|
209 |
+
max_lines=30,
|
210 |
+
show_copy_button=True,
|
211 |
+
# Add some visual cues for logs
|
212 |
+
container=True # Gives it a distinct container style
|
213 |
+
)
|
214 |
+
|
215 |
+
# --- Define Interactions ---
|
216 |
+
|
217 |
+
# Button click triggers the main processing function
|
218 |
+
# The outputs list maps the function's return values to UI components
|
219 |
+
generate_button.click(
|
220 |
+
fn=process_prompt_and_generate,
|
221 |
+
inputs=[
|
222 |
+
prompt_input,
|
223 |
+
image_resolution,
|
224 |
+
guidance_scale,
|
225 |
+
seed,
|
226 |
+
animation_frames,
|
227 |
+
animation_style
|
228 |
+
],
|
229 |
+
outputs=[
|
230 |
+
original_prompt_output,
|
231 |
+
enhanced_prompt_output,
|
232 |
+
generated_image_output,
|
233 |
+
generated_animation_output,
|
234 |
+
res_out, # Catch individual params to reconstruct metadata
|
235 |
+
gs_out,
|
236 |
+
seed_out,
|
237 |
+
frames_out,
|
238 |
+
style_out,
|
239 |
+
logs_output, # Logs are updated incrementally/finally
|
240 |
+
status_display # Status is updated incrementally/finally
|
241 |
+
]
|
242 |
+
)
|
243 |
+
|
244 |
+
# Update the combined parameters display after the main function runs
|
245 |
+
# This uses the individual output components as inputs for a new function
|
246 |
+
def update_parameters_display(res, gs, seed, frames, style):
|
247 |
+
if not res: # Check if results exist
|
248 |
+
return ""
|
249 |
+
metadata = f"Resolution: {res}px\nGuidance Scale: {gs}\nSeed: {seed}\nFrames: {frames}\nStyle: {style}"
|
250 |
+
return metadata
|
251 |
+
|
252 |
+
# Add a state component to hold the output parameters temporarily
|
253 |
+
# Or simply chain the update after the main click, using the same outputs
|
254 |
+
# Let's chain it for simplicity here. The order matters.
|
255 |
+
# This click event fires AFTER the main click event completes and updates its outputs.
|
256 |
+
# It takes the updated outputs as its inputs.
|
257 |
+
generate_button.click(
|
258 |
+
fn=update_parameters_display,
|
259 |
+
inputs=[res_out, gs_out, seed_out, frames_out, style_out],
|
260 |
+
outputs=[parameters_used_output]
|
261 |
+
)
|
262 |
+
|
263 |
+
# Randomize Seed Button Interaction
|
264 |
+
def randomize():
|
265 |
+
return random.randint(1, 1000000) # Generate a random seed
|
266 |
+
|
267 |
+
randomize_seed_button.click(
|
268 |
+
fn=randomize,
|
269 |
+
inputs=[],
|
270 |
+
outputs=[seed] # Update the seed number input field
|
271 |
+
)
|
272 |
+
|
273 |
+
|
274 |
+
# --- Launch the App ---
|
275 |
+
if __name__ == "__main__":
|
276 |
+
print("Gradio AI Creative Studio is starting...")
|
277 |
+
demo.launch()
|
278 |
+
print("App launched!")
|