mgbam commited on
Commit
3c54be4
Β·
verified Β·
1 Parent(s): db01582

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +60 -73
app.py CHANGED
@@ -103,7 +103,7 @@ body, .gradio-container { background-color: #0F0F1A !important; color: #D0D0E0 !
103
  def create_placeholder_image(text="Processing...", size=(512, 512), color="#23233A", text_color="#E0E0FF"):
104
  img = Image.new('RGB', size, color=color); draw = ImageDraw.Draw(img)
105
  try: font_path = "arial.ttf" if os.path.exists("arial.ttf") else None
106
- except: font_path = None # Handle potential OS errors accessing font list
107
  try: font = ImageFont.truetype(font_path, 40) if font_path else ImageFont.load_default()
108
  except IOError: font = ImageFont.load_default()
109
  if hasattr(draw, 'textbbox'): bbox = draw.textbbox((0,0), text, font=font); tw, th = bbox[2]-bbox[0], bbox[3]-bbox[1]
@@ -117,64 +117,57 @@ def add_scene_to_story_orchestrator(
117
  narrative_length: str, image_quality: str,
118
  progress=gr.Progress(track_tqdm=True)
119
  ):
 
 
 
120
  if not current_story_obj: current_story_obj = Story()
121
 
122
  log_accumulator = [f"**πŸš€ Scene {current_story_obj.current_scene_number + 1} - {time.strftime('%H:%M:%S')}**"]
123
 
 
 
 
 
 
 
 
 
 
 
 
124
  # Initial UI update using direct component updates in yield by component variable name
125
  yield {
126
  output_status_bar: gr.HTML(value=f"<p class='processing_text status_text'>🌌 Weaving Scene {current_story_obj.current_scene_number + 1}...</p>"),
127
  output_latest_scene_image: gr.Image(value=create_placeholder_image("🎨 Conjuring visuals..."), visible=True),
128
  output_latest_scene_narrative: gr.Markdown(value=" Musing narrative...", visible=True),
129
- engage_button: gr.Button(interactive=False),
130
  surprise_button: gr.Button(interactive=False),
131
  output_interaction_log_markdown: gr.Markdown(value="\n".join(log_accumulator))
132
  }
133
 
134
- # Prepare a dictionary to hold final return values for the .click() outputs list
135
- # Initialize with current state or placeholders
136
- final_return_dict = {
137
- "story_state": current_story_obj,
138
- "gallery": current_story_obj.get_all_scenes_for_gallery_display(), # Initial gallery
139
- "latest_image": create_placeholder_image("Pending..."),
140
- "latest_narrative": "## Pending...\nNarrative generation in progress.",
141
- "status_bar": "<p class='processing_text status_text'>Processing...</p>",
142
- "log": "\n".join(log_accumulator)
143
- }
144
-
145
  try:
146
- start_time = time.time()
147
-
148
  if not scene_prompt_text.strip():
149
  raise ValueError("Scene prompt cannot be empty!")
150
 
151
  # --- 1. Generate Narrative Text ---
152
  progress(0.1, desc="✍️ Crafting narrative...")
153
- narrative_text_generated = f"Narrative Error: Generation failed for '{scene_prompt_text[:30]}...'."
154
  text_model_info = TEXT_MODELS.get(text_model_key)
155
  if text_model_info and text_model_info["type"] != "none":
156
- system_p = get_narrative_system_prompt("default")
157
- prev_narrative = current_story_obj.get_last_scene_narrative()
158
  user_p = format_narrative_user_prompt(scene_prompt_text, prev_narrative)
159
- log_accumulator.append(f" Narrative: Using {text_model_key} ({text_model_info['id']}). Length aim: {narrative_length}")
160
  text_response = None
161
  if text_model_info["type"] == "gemini": text_response = generate_text_gemini(user_p, model_id=text_model_info["id"], system_prompt=system_p, max_tokens=768 if narrative_length.startswith("Detailed") else 400)
162
  elif text_model_info["type"] == "hf_text": text_response = generate_text_hf(user_p, model_id=text_model_info["id"], system_prompt=system_p, max_tokens=768 if narrative_length.startswith("Detailed") else 400)
163
-
164
- if text_response and text_response.success:
165
- narrative_text_generated = basic_text_cleanup(text_response.text)
166
- log_accumulator.append(f" Narrative: Success. (Snippet: {narrative_text_generated[:50]}...)")
167
- elif text_response:
168
- narrative_text_generated = f"**Narrative Error ({text_model_key}):** {text_response.error}"
169
- log_accumulator.append(f" Narrative: FAILED - {text_response.error}")
170
- else:
171
- log_accumulator.append(f" Narrative: FAILED - No response object from {text_model_key}.")
172
- else:
173
- narrative_text_generated = "**Narrative Error:** Selected text model not available or misconfigured."
174
- log_accumulator.append(f" Narrative: FAILED - Model '{text_model_key}' not available.")
175
 
176
- final_return_dict["latest_narrative"] = f"## Scene Idea: {scene_prompt_text}\n\n{narrative_text_generated}"
177
- yield { output_latest_scene_narrative: gr.Markdown(value=final_return_dict["latest_narrative"]),
178
  output_interaction_log_markdown: gr.Markdown(value="\n".join(log_accumulator)) }
179
 
180
  # --- 2. Generate Image ---
@@ -191,22 +184,13 @@ def add_scene_to_story_orchestrator(
191
  image_response = None
192
  if selected_image_provider_type == "stability_ai": image_response = generate_image_stabilityai(full_image_prompt, negative_prompt=negative_prompt_text or COMMON_NEGATIVE_PROMPTS, steps=40 if image_quality=="High Detail" else 25)
193
  elif selected_image_provider_type == "dalle": image_response = generate_image_dalle(full_image_prompt, quality="hd" if image_quality=="High Detail" else "standard")
194
-
195
- if image_response and image_response.success:
196
- image_generated_pil = image_response.image
197
- log_accumulator.append(f" Image: Success from {image_response.provider}.")
198
- elif image_response:
199
- image_generation_error_message = f"**Image Error ({image_response.provider}):** {image_response.error}"
200
- log_accumulator.append(f" Image: FAILED - {image_response.error}")
201
- else:
202
- image_generation_error_message = f"**Image Error:** No response object from {image_provider_key} service."
203
- log_accumulator.append(f" Image: FAILED - No response object from {image_provider_key}.")
204
- else:
205
- image_generation_error_message = "**Image Error:** Selected image provider not available or misconfigured."
206
- log_accumulator.append(f" Image: FAILED - Provider '{image_provider_key}' not available.")
207
 
208
- final_return_dict["latest_image"] = image_generated_pil if image_generated_pil else create_placeholder_image("Image Gen Failed", color="#401010")
209
- yield { output_latest_scene_image: gr.Image(value=final_return_dict["latest_image"]),
210
  output_interaction_log_markdown: gr.Markdown(value="\n".join(log_accumulator)) }
211
 
212
  # --- 3. Add Scene to Story Object ---
@@ -223,40 +207,42 @@ def add_scene_to_story_orchestrator(
223
  image_provider=image_provider_key if selected_image_provider_type != "none" else "N/A",
224
  error_message=final_scene_error
225
  )
226
- final_return_dict["story_state"] = current_story_obj # Update story state in final dict
227
- log_accumulator.append(f" Scene {current_story_obj.current_scene_number} processed and added to story object.")
228
 
229
- # --- 4. Prepare Final Outputs for Gradio ---
230
- final_return_dict["gallery"] = current_story_obj.get_all_scenes_for_gallery_display()
231
- _ , final_return_dict["latest_narrative"] = current_story_obj.get_latest_scene_details_for_display() # Update narrative for final return
 
232
 
233
- final_return_dict["status_bar"] = f"<p class='error_text status_text'>Scene {current_story_obj.current_scene_number} added with errors.</p>" if final_scene_error else f"<p class='success_text status_text'>🌌 Scene {current_story_obj.current_scene_number} woven!</p>"
 
234
 
235
  progress(1.0, desc="Scene Complete!")
236
 
237
  except ValueError as ve:
238
  log_accumulator.append(f"\n**INPUT/CONFIG ERROR:** {ve}")
239
- final_return_dict["status_bar"] = f"<p class='error_text status_text'>❌ CONFIGURATION ERROR: {ve}</p>"
240
- final_return_dict["latest_narrative"] = f"## Error\n{ve}"
241
  except Exception as e:
242
  log_accumulator.append(f"\n**UNEXPECTED RUNTIME ERROR:** {type(e).__name__} - {e}\n{traceback.format_exc()}")
243
- final_return_dict["status_bar"] = f"<p class='error_text status_text'>❌ UNEXPECTED ERROR: {e}. Check logs.</p>"
244
- final_return_dict["latest_narrative"] = f"## Unexpected Error\n{e}\nSee log for details."
245
  finally:
246
- log_accumulator.append(f" Cycle ended at {time.strftime('%H:%M:%S')}. Total time: {time.time() - (start_time if 'start_time' in locals() else time.time()):.2f}s")
247
- final_return_dict["log"] = "\n".join(log_accumulator)
248
- # Final yield to re-enable buttons, this will be overridden by the return for other components
249
- yield { engage_button: gr.Button(interactive=True), surprise_button: gr.Button(interactive=True) }
 
 
 
 
 
 
 
 
 
250
 
251
- # Final return statement for the .click() handler
252
- return (
253
- final_return_dict["story_state"],
254
- final_return_dict["gallery"],
255
- final_return_dict["latest_image"],
256
- gr.Markdown(value=final_return_dict["latest_narrative"]),
257
- gr.HTML(value=final_return_dict["status_bar"]),
258
- gr.Markdown(value=final_return_dict["log"])
259
- )
260
 
261
  def clear_story_state_ui_wrapper():
262
  new_story = Story()
@@ -317,7 +303,6 @@ with gr.Blocks(theme=omega_theme, css=omega_css, title="✨ StoryVerse Omega ✨
317
  image_quality_dropdown = gr.Dropdown(["Standard", "High Detail", "Sketch Concept"], value="Standard", label="Image Detail/Style")
318
 
319
  with gr.Row(elem_classes=["compact-row"], equal_height=True):
320
- # Assign these buttons to Python variables to be updated by yield
321
  engage_button = gr.Button("🌌 Weave This Scene!", variant="primary", scale=3, icon="✨")
322
  surprise_button = gr.Button("🎲 Surprise Me!", variant="secondary", scale=1, icon="🎁")
323
  clear_story_button = gr.Button("πŸ—‘οΈ New Story", variant="stop", scale=1, icon="♻️")
@@ -346,7 +331,7 @@ with gr.Blocks(theme=omega_theme, css=omega_css, title="✨ StoryVerse Omega ✨
346
  text_model_dropdown, image_provider_dropdown,
347
  narrative_length_dropdown, image_quality_dropdown
348
  ],
349
- outputs=[ # These components are updated by the FINAL return of the orchestrator
350
  story_state_output,
351
  output_gallery,
352
  output_latest_scene_image,
@@ -375,6 +360,8 @@ with gr.Blocks(theme=omega_theme, css=omega_css, title="✨ StoryVerse Omega ✨
375
  examples=[
376
  ["A lone, weary traveler on a mechanical steed crosses a vast, crimson desert under twin suns. Dust devils dance in the distance.", "Sci-Fi Western", "Moebius", "greenery, water, modern city"],
377
  ["Deep within an ancient, bioluminescent forest, a hidden civilization of sentient fungi perform a mystical ritual around a pulsating crystal.", "Psychedelic Fantasy", "Alex Grey", "technology, buildings, roads"],
 
 
378
  ],
379
  inputs=[scene_prompt_input, image_style_input, artist_style_input, negative_prompt_input],
380
  label="🌌 Example Universes to Weave 🌌",
 
103
  def create_placeholder_image(text="Processing...", size=(512, 512), color="#23233A", text_color="#E0E0FF"):
104
  img = Image.new('RGB', size, color=color); draw = ImageDraw.Draw(img)
105
  try: font_path = "arial.ttf" if os.path.exists("arial.ttf") else None
106
+ except: font_path = None
107
  try: font = ImageFont.truetype(font_path, 40) if font_path else ImageFont.load_default()
108
  except IOError: font = ImageFont.load_default()
109
  if hasattr(draw, 'textbbox'): bbox = draw.textbbox((0,0), text, font=font); tw, th = bbox[2]-bbox[0], bbox[3]-bbox[1]
 
117
  narrative_length: str, image_quality: str,
118
  progress=gr.Progress(track_tqdm=True)
119
  ):
120
+ # Initialize start_time here
121
+ start_time = time.time()
122
+
123
  if not current_story_obj: current_story_obj = Story()
124
 
125
  log_accumulator = [f"**πŸš€ Scene {current_story_obj.current_scene_number + 1} - {time.strftime('%H:%M:%S')}**"]
126
 
127
+ # Define placeholders for the final return tuple values
128
+ # This ensures they exist even if errors occur early.
129
+ # Order must match engage_button.click outputs list
130
+ ret_story_state = current_story_obj
131
+ ret_gallery = current_story_obj.get_all_scenes_for_gallery_display()
132
+ ret_latest_image = None
133
+ ret_latest_narrative = gr.Markdown(value="## Error\nProcessing did not complete.")
134
+ ret_status_bar = gr.HTML(value="<p class='error_text status_text'>An error occurred during processing.</p>")
135
+ ret_log = gr.Markdown(value="\n".join(log_accumulator))
136
+
137
+
138
  # Initial UI update using direct component updates in yield by component variable name
139
  yield {
140
  output_status_bar: gr.HTML(value=f"<p class='processing_text status_text'>🌌 Weaving Scene {current_story_obj.current_scene_number + 1}...</p>"),
141
  output_latest_scene_image: gr.Image(value=create_placeholder_image("🎨 Conjuring visuals..."), visible=True),
142
  output_latest_scene_narrative: gr.Markdown(value=" Musing narrative...", visible=True),
143
+ engage_button: gr.Button(interactive=False), # Disable button
144
  surprise_button: gr.Button(interactive=False),
145
  output_interaction_log_markdown: gr.Markdown(value="\n".join(log_accumulator))
146
  }
147
 
 
 
 
 
 
 
 
 
 
 
 
148
  try:
 
 
149
  if not scene_prompt_text.strip():
150
  raise ValueError("Scene prompt cannot be empty!")
151
 
152
  # --- 1. Generate Narrative Text ---
153
  progress(0.1, desc="✍️ Crafting narrative...")
154
+ narrative_text_generated = f"Narrative Error: Init failed."
155
  text_model_info = TEXT_MODELS.get(text_model_key)
156
  if text_model_info and text_model_info["type"] != "none":
157
+ system_p = get_narrative_system_prompt("default")
158
+ prev_narrative = current_story_obj.get_last_scene_narrative()
159
  user_p = format_narrative_user_prompt(scene_prompt_text, prev_narrative)
160
+ log_accumulator.append(f" Narrative: Using {text_model_key} ({text_model_info['id']}). Length: {narrative_length}")
161
  text_response = None
162
  if text_model_info["type"] == "gemini": text_response = generate_text_gemini(user_p, model_id=text_model_info["id"], system_prompt=system_p, max_tokens=768 if narrative_length.startswith("Detailed") else 400)
163
  elif text_model_info["type"] == "hf_text": text_response = generate_text_hf(user_p, model_id=text_model_info["id"], system_prompt=system_p, max_tokens=768 if narrative_length.startswith("Detailed") else 400)
164
+ if text_response and text_response.success: narrative_text_generated = basic_text_cleanup(text_response.text); log_accumulator.append(f" Narrative: Success.")
165
+ elif text_response: narrative_text_generated = f"**Narrative Error ({text_model_key}):** {text_response.error}"; log_accumulator.append(f" Narrative: FAILED - {text_response.error}")
166
+ else: log_accumulator.append(f" Narrative: FAILED - No response from {text_model_key}.")
167
+ else: narrative_text_generated = "**Narrative Error:** Text model unavailable."; log_accumulator.append(f" Narrative: FAILED - Model '{text_model_key}' unavailable.")
 
 
 
 
 
 
 
 
168
 
169
+ ret_latest_narrative = gr.Markdown(value=f"## Scene Idea: {scene_prompt_text}\n\n{narrative_text_generated}")
170
+ yield { output_latest_scene_narrative: ret_latest_narrative,
171
  output_interaction_log_markdown: gr.Markdown(value="\n".join(log_accumulator)) }
172
 
173
  # --- 2. Generate Image ---
 
184
  image_response = None
185
  if selected_image_provider_type == "stability_ai": image_response = generate_image_stabilityai(full_image_prompt, negative_prompt=negative_prompt_text or COMMON_NEGATIVE_PROMPTS, steps=40 if image_quality=="High Detail" else 25)
186
  elif selected_image_provider_type == "dalle": image_response = generate_image_dalle(full_image_prompt, quality="hd" if image_quality=="High Detail" else "standard")
187
+ if image_response and image_response.success: image_generated_pil = image_response.image; log_accumulator.append(f" Image: Success.")
188
+ elif image_response: image_generation_error_message = f"**Image Error ({image_response.provider}):** {image_response.error}"; log_accumulator.append(f" Image: FAILED - {image_response.error}")
189
+ else: image_generation_error_message = f"**Image Error:** No response from {image_provider_key}."; log_accumulator.append(f" Image: FAILED - No response.")
190
+ else: image_generation_error_message = "**Image Error:** Image provider unavailable."; log_accumulator.append(f" Image: FAILED - Provider '{image_provider_key}' unavailable.")
 
 
 
 
 
 
 
 
 
191
 
192
+ ret_latest_image = image_generated_pil if image_generated_pil else create_placeholder_image("Image Gen Failed", color="#401010")
193
+ yield { output_latest_scene_image: gr.Image(value=ret_latest_image),
194
  output_interaction_log_markdown: gr.Markdown(value="\n".join(log_accumulator)) }
195
 
196
  # --- 3. Add Scene to Story Object ---
 
207
  image_provider=image_provider_key if selected_image_provider_type != "none" else "N/A",
208
  error_message=final_scene_error
209
  )
210
+ ret_story_state = current_story_obj
211
+ log_accumulator.append(f" Scene {current_story_obj.current_scene_number} processed and added.")
212
 
213
+ # --- 4. Prepare Final Values for Return Tuple ---
214
+ ret_gallery = current_story_obj.get_all_scenes_for_gallery_display()
215
+ _ , latest_narr_for_display_final_str = current_story_obj.get_latest_scene_details_for_display()
216
+ ret_latest_narrative = gr.Markdown(value=latest_narr_for_display_final_str)
217
 
218
+ status_html_str = f"<p class='error_text status_text'>Scene {current_story_obj.current_scene_number} added with errors.</p>" if final_scene_error else f"<p class='success_text status_text'>🌌 Scene {current_story_obj.current_scene_number} woven!</p>"
219
+ ret_status_bar = gr.HTML(value=status_html_str)
220
 
221
  progress(1.0, desc="Scene Complete!")
222
 
223
  except ValueError as ve:
224
  log_accumulator.append(f"\n**INPUT/CONFIG ERROR:** {ve}")
225
+ ret_status_bar = gr.HTML(value=f"<p class='error_text status_text'>❌ CONFIGURATION ERROR: {ve}</p>")
226
+ ret_latest_narrative = gr.Markdown(value=f"## Error\n{ve}")
227
  except Exception as e:
228
  log_accumulator.append(f"\n**UNEXPECTED RUNTIME ERROR:** {type(e).__name__} - {e}\n{traceback.format_exc()}")
229
+ ret_status_bar = gr.HTML(value=f"<p class='error_text status_text'>❌ UNEXPECTED ERROR: {type(e).__name__}. Check logs.</p>")
230
+ ret_latest_narrative = gr.Markdown(value=f"## Unexpected Error\n{type(e).__name__}: {e}\nSee log for details.")
231
  finally:
232
+ current_total_time = time.time() - start_time
233
+ log_accumulator.append(f" Cycle ended at {time.strftime('%H:%M:%S')}. Total time: {current_total_time:.2f}s")
234
+ ret_log = gr.Markdown(value="\n".join(log_accumulator))
235
+
236
+ # This yield is only for button states, does not affect the main 'return'
237
+ yield {
238
+ engage_button: gr.Button(interactive=True),
239
+ surprise_button: gr.Button(interactive=True),
240
+ output_interaction_log_markdown: ret_log # Update log one last time via yield
241
+ }
242
+
243
+ # Final return for the .click() handler's `outputs` list
244
+ return ret_story_state, ret_gallery, ret_latest_image, ret_latest_narrative, ret_status_bar, ret_log
245
 
 
 
 
 
 
 
 
 
 
246
 
247
  def clear_story_state_ui_wrapper():
248
  new_story = Story()
 
303
  image_quality_dropdown = gr.Dropdown(["Standard", "High Detail", "Sketch Concept"], value="Standard", label="Image Detail/Style")
304
 
305
  with gr.Row(elem_classes=["compact-row"], equal_height=True):
 
306
  engage_button = gr.Button("🌌 Weave This Scene!", variant="primary", scale=3, icon="✨")
307
  surprise_button = gr.Button("🎲 Surprise Me!", variant="secondary", scale=1, icon="🎁")
308
  clear_story_button = gr.Button("πŸ—‘οΈ New Story", variant="stop", scale=1, icon="♻️")
 
331
  text_model_dropdown, image_provider_dropdown,
332
  narrative_length_dropdown, image_quality_dropdown
333
  ],
334
+ outputs=[ # These components are updated by the FINAL return tuple of the orchestrator
335
  story_state_output,
336
  output_gallery,
337
  output_latest_scene_image,
 
360
  examples=[
361
  ["A lone, weary traveler on a mechanical steed crosses a vast, crimson desert under twin suns. Dust devils dance in the distance.", "Sci-Fi Western", "Moebius", "greenery, water, modern city"],
362
  ["Deep within an ancient, bioluminescent forest, a hidden civilization of sentient fungi perform a mystical ritual around a pulsating crystal.", "Psychedelic Fantasy", "Alex Grey", "technology, buildings, roads"],
363
+ ["A child sits on a crescent moon, fishing for stars in a swirling nebula. A friendly space whale swims nearby.", "Whimsical Cosmic", "James Jean", "realistic, dark, scary"],
364
+ ["A grand, baroque library where the books fly freely and whisper forgotten lore to those who listen closely.", "Magical Realism", "Remedios Varo", "minimalist, simple, technology"]
365
  ],
366
  inputs=[scene_prompt_input, image_style_input, artist_style_input, negative_prompt_input],
367
  label="🌌 Example Universes to Weave 🌌",