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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +70 -68
app.py CHANGED
@@ -20,9 +20,8 @@ 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
- # Configure models
26
  genai.configure(api_key=api_key)
27
  text_model = genai.GenerativeModel("gemini-1.5-flash")
28
  image_model = genai.GenerativeModel(
@@ -31,7 +30,7 @@ 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,25 +95,18 @@ def generate_pdf(images, explanations):
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,29 +116,14 @@ def generate_scene(num_scenes, theme, char_count, character_names, dialogue,
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)
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,60 +134,60 @@ Continue the story logically based on previous scenes (if any):
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
 
 
 
 
 
210
  status = gr.Markdown()
211
  image_output = gr.Image(label="πŸ–ΌοΈ Scene Image", type="pil")
212
  summary_output = gr.Markdown(label="πŸ“ Scene Summary")
213
  explanation_output = gr.Textbox(label="πŸ“– Scene Explanation", lines=6)
 
214
 
215
  with gr.Row():
216
  tts_btn = gr.Button("πŸ”Š Read Aloud")
@@ -220,32 +197,57 @@ with gr.Blocks(title="Scene-by-Scene Story Generator") as demo:
220
  txt_file = gr.File(label="πŸ“„ Explanations (.txt)")
221
  pdf_file = gr.File(label="πŸ“˜ Scene PDF")
222
 
223
- # Persistent session states
224
  scene_images = gr.State([])
225
  scene_explanations = gr.State([])
226
  scene_summaries = gr.State([])
 
227
 
228
  generate_btn.click(
229
  fn=generate_scene,
230
  inputs=[
231
  scene_total, theme, char_count, character_names, dialogue,
 
 
 
 
232
  scene_images, scene_summaries, scene_explanations,
233
- char_styles, char_moods, bg_style, dialogue_speaker
 
 
 
 
 
 
 
 
234
  ],
235
  outputs=[
236
  image_output, summary_output, explanation_output,
237
  scene_images, scene_summaries, scene_explanations,
238
- status, done_btn
 
 
 
 
 
 
 
 
 
 
 
 
 
239
  ]
240
  )
241
 
242
  ai_coauthor_btn.click(
243
  fn=ai_write_scene,
244
  inputs=[theme, scene_total, scene_summaries],
245
- outputs=[character_names, dialogue, dialogue_speaker, char_styles, char_moods, bg_style, status]
246
  )
247
 
248
-
249
  done_btn.click(
250
  fn=finalize_story,
251
  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
  genai.configure(api_key=api_key)
26
  text_model = genai.GenerativeModel("gemini-1.5-flash")
27
  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
  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
  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
  {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
  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],