fizzarif7 commited on
Commit
c733ec4
Β·
verified Β·
1 Parent(s): f316c14

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +78 -50
app.py CHANGED
@@ -20,8 +20,9 @@ api_key = os.getenv("GOOGLE_API_KEY")
20
  hf_token = os.getenv("HF_token")
21
 
22
  if not api_key or not hf_token:
23
- raise EnvironmentError("Missing API keys. Check GOOGLE_API_KEY and HF_TOKEN in .env.")
24
 
 
25
  genai.configure(api_key=api_key)
26
  text_model = genai.GenerativeModel("gemini-1.5-flash")
27
  image_model = genai.GenerativeModel(
@@ -30,7 +31,7 @@ image_model = genai.GenerativeModel(
30
  )
31
  hf_client = InferenceClient(token=hf_token)
32
 
33
- # -------------- Utility Functions --------------
34
 
35
  def generate_image_from_text(prompt):
36
  try:
@@ -95,18 +96,25 @@ def generate_pdf(images, explanations):
95
  doc.build(story)
96
  return tmp.name
97
 
98
- # ------------------ Core Scene Logic ------------------
99
 
100
  def generate_scene(num_scenes, theme, char_count, character_names, dialogue,
101
- images, summaries, explanations, current_scene_index):
 
102
 
103
- if current_scene_index >= int(num_scenes):
104
  return gr.update(), gr.update(), gr.update(), images, summaries, explanations, \
105
- "βœ… All scenes have been generated.", images[-1], current_scene_index
 
 
 
 
 
 
106
 
107
- prompt = f"Scene {current_scene_index + 1} set in {theme}. Number of characters: {char_count}. Characters: {character_names}."
108
  if dialogue:
109
- prompt += f' Include this dialogue: "{dialogue}".'
 
110
 
111
  image = generate_image_from_text(prompt)
112
  summary = summarize_scene(prompt)
@@ -116,14 +124,29 @@ def generate_scene(num_scenes, theme, char_count, character_names, dialogue,
116
  summaries.append(summary)
117
  explanations.append(explanation)
118
 
119
- status = f"βœ… Scene {current_scene_index + 1} of {int(num_scenes)} generated."
120
- return image, summary, explanation, images, summaries, explanations, status, image, current_scene_index + 1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
 
122
  def ai_write_scene(theme, total_scenes, scene_summaries):
123
  try:
124
  scene_index = len(scene_summaries) + 1
125
  if scene_index > int(total_scenes):
126
- return "", "", f"βœ… All {total_scenes} scenes completed."
127
 
128
  story_so_far = "\n".join([f"Scene {i+1}: {s}" for i, s in enumerate(scene_summaries)]) if scene_summaries else ""
129
  prompt = f"""
@@ -134,60 +157,64 @@ Continue the story logically based on previous scenes (if any):
134
  {story_so_far}
135
 
136
  Return:
137
- 1. Character names,
138
- 2. One line of dialogue
 
 
 
 
 
139
  """
140
-
141
  response = text_model.generate_content(prompt).text.strip()
142
- lines = response.split("\n")
143
- char_names = lines[0] if lines else ""
144
- dialogue = lines[1] if len(lines) > 1 else ""
145
-
146
- return char_names, dialogue, f"πŸ“ Scene {scene_index} prompt generated."
 
 
 
 
147
  except Exception as e:
148
  print("AI write error:", e)
149
- return "", "", "⚠️ AI scene generation failed."
150
 
151
- def finalize_story(images, explanations):
152
- if not images or not explanations:
153
- return None, None
154
-
155
- pdf = generate_pdf(images, explanations)
156
-
157
- with tempfile.NamedTemporaryFile(delete=False, suffix=".txt", mode="w", encoding="utf-8") as txt:
158
- for i, exp in enumerate(explanations):
159
- txt.write(f"Scene {i+1}:\n{exp}\n\n")
160
- txt_path = txt.name
161
 
162
- return txt_path, pdf
163
-
164
- # ------------------ UI ------------------
165
 
166
  with gr.Blocks(title="Scene-by-Scene Story Generator") as demo:
167
  gr.Markdown("## 🎬 AI Scene-by-Scene Story Creator")
 
168
 
169
  with gr.Accordion("🧩 Story Setup", open=True):
170
  scene_total = gr.Number(label="πŸ”’ Number of Scenes", precision=0, value=3)
171
  theme = gr.Textbox(label="🌍 Global Theme", placeholder="e.g. A magical forest full of glowing creatures")
172
 
 
 
173
  with gr.Row():
174
  char_count = gr.Number(label="πŸ‘₯ Number of Characters", precision=0, value=2)
175
- character_names = gr.Textbox(label="πŸ§™β€β™‚οΈ Character Names")
176
- dialogue = gr.Textbox(label="πŸ’¬ Dialogue (optional)")
 
 
 
 
 
 
177
 
178
  with gr.Row():
179
  generate_btn = gr.Button("βž• Generate This Scene")
180
  ai_coauthor_btn = gr.Button("πŸ€– Let AI Write This One")
 
 
 
181
 
182
- with gr.Row():
183
- recreate_btn = gr.Button("πŸ”„ Recreate Scene")
184
- next_scene_btn = gr.Button("⏭️ Next Scene")
185
 
186
  status = gr.Markdown()
187
  image_output = gr.Image(label="πŸ–ΌοΈ Scene Image", type="pil")
188
  summary_output = gr.Markdown(label="πŸ“ Scene Summary")
189
  explanation_output = gr.Textbox(label="πŸ“– Scene Explanation", lines=6)
190
- last_image_display = gr.Image(label="πŸ–ΌοΈ Last Scene Image")
191
 
192
  with gr.Row():
193
  tts_btn = gr.Button("πŸ”Š Read Aloud")
@@ -197,57 +224,58 @@ with gr.Blocks(title="Scene-by-Scene Story Generator") as demo:
197
  txt_file = gr.File(label="πŸ“„ Explanations (.txt)")
198
  pdf_file = gr.File(label="πŸ“˜ Scene PDF")
199
 
200
- # States
201
  scene_images = gr.State([])
202
  scene_explanations = gr.State([])
203
  scene_summaries = gr.State([])
204
- current_scene_index = gr.State(0)
205
 
206
  generate_btn.click(
207
  fn=generate_scene,
208
  inputs=[
209
  scene_total, theme, char_count, character_names, dialogue,
210
- scene_images, scene_summaries, scene_explanations, current_scene_index
211
  ],
212
  outputs=[
213
  image_output, summary_output, explanation_output,
214
  scene_images, scene_summaries, scene_explanations,
215
- status, last_image_display, current_scene_index
216
  ]
217
  )
218
 
219
  recreate_btn.click(
220
- fn=generate_scene,
221
  inputs=[
222
  scene_total, theme, char_count, character_names, dialogue,
223
- scene_images, scene_summaries, scene_explanations, current_scene_index
224
  ],
225
  outputs=[
226
  image_output, summary_output, explanation_output,
227
  scene_images, scene_summaries, scene_explanations,
228
- status, last_image_display, current_scene_index
229
  ]
230
  )
231
 
232
- next_scene_btn.click(
233
  fn=generate_scene,
234
  inputs=[
235
  scene_total, theme, char_count, character_names, dialogue,
236
- scene_images, scene_summaries, scene_explanations, current_scene_index
237
  ],
238
  outputs=[
239
  image_output, summary_output, explanation_output,
240
  scene_images, scene_summaries, scene_explanations,
241
- status, last_image_display, current_scene_index
242
  ]
243
  )
244
 
 
245
  ai_coauthor_btn.click(
246
  fn=ai_write_scene,
247
  inputs=[theme, scene_total, scene_summaries],
248
- outputs=[character_names, dialogue, status]
249
  )
250
 
 
251
  done_btn.click(
252
  fn=finalize_story,
253
  inputs=[scene_images, scene_explanations],
 
20
  hf_token = os.getenv("HF_token")
21
 
22
  if not api_key or not hf_token:
23
+ raise EnvironmentError("Missing API keys. Check GOOGLE_API_KEY and HF_token in .env.")
24
 
25
+ # Configure models
26
  genai.configure(api_key=api_key)
27
  text_model = genai.GenerativeModel("gemini-1.5-flash")
28
  image_model = genai.GenerativeModel(
 
31
  )
32
  hf_client = InferenceClient(token=hf_token)
33
 
34
+ # -------------------- Utility Functions --------------------
35
 
36
  def generate_image_from_text(prompt):
37
  try:
 
96
  doc.build(story)
97
  return tmp.name
98
 
99
+ # -------------------- Core Logic --------------------
100
 
101
  def generate_scene(num_scenes, theme, char_count, character_names, dialogue,
102
+ images, summaries, explanations,
103
+ char_styles, char_moods, bg_style, dialogue_speaker):
104
 
105
+ if len(images) >= int(num_scenes):
106
  return gr.update(), gr.update(), gr.update(), images, summaries, explanations, \
107
+ f"βœ… All {num_scenes} scenes have been generated.", gr.update(visible=True)
108
+
109
+ prompt = (
110
+ f"Scene {len(images)+1} set in {theme}. Number of characters: {char_count}. "
111
+ f"Characters: {character_names}. Outfits: {char_styles}. Mood: {char_moods}. "
112
+ f"Style: {bg_style}."
113
+ )
114
 
 
115
  if dialogue:
116
+ prompt += f' The character "{dialogue_speaker}" says: "{dialogue}". '
117
+ prompt += f' Please visualize this as a speech bubble above {dialogue_speaker}, like in a cartoon.'
118
 
119
  image = generate_image_from_text(prompt)
120
  summary = summarize_scene(prompt)
 
124
  summaries.append(summary)
125
  explanations.append(explanation)
126
 
127
+ status = f"βœ… Scene {len(images)} of {int(num_scenes)} generated."
128
+ done_visible = len(images) == int(num_scenes)
129
+
130
+ return image, summary, explanation, images, summaries, explanations, status, gr.update(visible=done_visible), image
131
+
132
+ def finalize_story(images, explanations):
133
+ if not images or not explanations:
134
+ return None, None
135
+
136
+ pdf = generate_pdf(images, explanations)
137
+
138
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".txt", mode="w", encoding="utf-8") as txt:
139
+ for i, exp in enumerate(explanations):
140
+ txt.write(f"Scene {i+1}:\n{exp}\n\n")
141
+ txt_path = txt.name
142
+
143
+ return txt_path, pdf
144
 
145
  def ai_write_scene(theme, total_scenes, scene_summaries):
146
  try:
147
  scene_index = len(scene_summaries) + 1
148
  if scene_index > int(total_scenes):
149
+ return "", "", "", "", "", "Fantasy", f"βœ… All {total_scenes} scenes completed."
150
 
151
  story_so_far = "\n".join([f"Scene {i+1}: {s}" for i, s in enumerate(scene_summaries)]) if scene_summaries else ""
152
  prompt = f"""
 
157
  {story_so_far}
158
 
159
  Return:
160
+ 1. Character names (existing or new),
161
+ 2. A single dialogue line,
162
+ 3. The speaker of that dialogue,
163
+ 4. Outfits worn,
164
+ 5. Characters' emotional moods,
165
+ 6. Background style (choose from: Realistic, Cartoon, Fantasy, Dark Fantasy).
166
+ Only provide the raw values, no headers.
167
  """
 
168
  response = text_model.generate_content(prompt).text.strip()
169
+ parts = [line.strip() for line in response.split("\n") if line.strip()]
170
+ char_names = parts[0] if len(parts) > 0 else ""
171
+ dialogue = parts[1] if len(parts) > 1 else ""
172
+ speaker = parts[2] if len(parts) > 2 else ""
173
+ outfits = parts[3] if len(parts) > 3 else ""
174
+ moods = parts[4] if len(parts) > 4 else ""
175
+ bg_style = parts[5] if len(parts) > 5 else "Fantasy"
176
+
177
+ return char_names, dialogue, speaker, outfits, moods, bg_style, f"πŸ“ Scene {scene_index} ready to generate."
178
  except Exception as e:
179
  print("AI write error:", e)
180
+ return "", "", "", "", "", "Fantasy", "⚠️ AI scene generation failed."
181
 
 
 
 
 
 
 
 
 
 
 
182
 
183
+ # -------------------- UI --------------------
 
 
184
 
185
  with gr.Blocks(title="Scene-by-Scene Story Generator") as demo:
186
  gr.Markdown("## 🎬 AI Scene-by-Scene Story Creator")
187
+ gr.Markdown("Describe your story one scene at a time, with AI-generated images, summaries, and explanations.")
188
 
189
  with gr.Accordion("🧩 Story Setup", open=True):
190
  scene_total = gr.Number(label="πŸ”’ Number of Scenes", precision=0, value=3)
191
  theme = gr.Textbox(label="🌍 Global Theme", placeholder="e.g. A magical forest full of glowing creatures")
192
 
193
+ gr.Markdown("### ✨ Describe Your Next Scene")
194
+
195
  with gr.Row():
196
  char_count = gr.Number(label="πŸ‘₯ Number of Characters", precision=0, value=2)
197
+ character_names = gr.Textbox(label="πŸ§™β€β™‚οΈ Character Names", placeholder="e.g. Elora, Bramble the Bear")
198
+ dialogue = gr.Textbox(label="πŸ’¬ Dialogue (optional)", placeholder="e.g. 'Protect the forest!'")
199
+
200
+ with gr.Row():
201
+ dialogue_speaker = gr.Textbox(label="πŸ—£οΈ Who says the dialogue?", placeholder="e.g. Bramble")
202
+ char_styles = gr.Textbox(label="πŸ§₯ Outfit Descriptions", placeholder="e.g. Elora wears a leafy cloak, Bramble has a warrior vest")
203
+ char_moods = gr.Textbox(label="😠 Character Moods", placeholder="e.g. Elora is cautious, Bramble is brave")
204
+ bg_style = gr.Dropdown(label="🎨 Background Style", choices=["Realistic", "Cartoon", "Fantasy", "Dark Fantasy"], value="Fantasy")
205
 
206
  with gr.Row():
207
  generate_btn = gr.Button("βž• Generate This Scene")
208
  ai_coauthor_btn = gr.Button("πŸ€– Let AI Write This One")
209
+ recreate_btn = gr.Button("πŸ”„ Recreate This Scene")
210
+ next_btn = gr.Button("⏭️ Next Scene")
211
+ last_image_display = gr.Image(label="πŸ“Έ Last Scene Image", type="pil")
212
 
 
 
 
213
 
214
  status = gr.Markdown()
215
  image_output = gr.Image(label="πŸ–ΌοΈ Scene Image", type="pil")
216
  summary_output = gr.Markdown(label="πŸ“ Scene Summary")
217
  explanation_output = gr.Textbox(label="πŸ“– Scene Explanation", lines=6)
 
218
 
219
  with gr.Row():
220
  tts_btn = gr.Button("πŸ”Š Read Aloud")
 
224
  txt_file = gr.File(label="πŸ“„ Explanations (.txt)")
225
  pdf_file = gr.File(label="πŸ“˜ Scene PDF")
226
 
227
+ # Persistent session states
228
  scene_images = gr.State([])
229
  scene_explanations = gr.State([])
230
  scene_summaries = gr.State([])
 
231
 
232
  generate_btn.click(
233
  fn=generate_scene,
234
  inputs=[
235
  scene_total, theme, char_count, character_names, dialogue,
236
+ scene_images, scene_summaries, scene_explanations
237
  ],
238
  outputs=[
239
  image_output, summary_output, explanation_output,
240
  scene_images, scene_summaries, scene_explanations,
241
+ status, done_btn, last_image_display
242
  ]
243
  )
244
 
245
  recreate_btn.click(
246
+ fn=lambda *args: generate_scene(*args[:-1], args[-3][:-1], args[-2][:-1], args[-1][:-1]),
247
  inputs=[
248
  scene_total, theme, char_count, character_names, dialogue,
249
+ scene_images, scene_summaries, scene_explanations
250
  ],
251
  outputs=[
252
  image_output, summary_output, explanation_output,
253
  scene_images, scene_summaries, scene_explanations,
254
+ status, done_btn, last_image_display
255
  ]
256
  )
257
 
258
+ next_btn.click(
259
  fn=generate_scene,
260
  inputs=[
261
  scene_total, theme, char_count, character_names, dialogue,
262
+ scene_images, scene_summaries, scene_explanations
263
  ],
264
  outputs=[
265
  image_output, summary_output, explanation_output,
266
  scene_images, scene_summaries, scene_explanations,
267
+ status, done_btn, last_image_display
268
  ]
269
  )
270
 
271
+
272
  ai_coauthor_btn.click(
273
  fn=ai_write_scene,
274
  inputs=[theme, scene_total, scene_summaries],
275
+ outputs=[character_names, dialogue, dialogue_speaker, char_styles, char_moods, bg_style, status]
276
  )
277
 
278
+
279
  done_btn.click(
280
  fn=finalize_story,
281
  inputs=[scene_images, scene_explanations],