Phani1008 commited on
Commit
048ddef
Β·
verified Β·
1 Parent(s): c15ef20

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +131 -27
app.py CHANGED
@@ -1,5 +1,7 @@
1
  import streamlit as st
2
  from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
 
 
3
  import json
4
  import textwrap
5
 
@@ -12,29 +14,59 @@ st.set_page_config(
12
  layout="wide"
13
  )
14
 
15
- st.title("🎬 AI Story β†’ Movie Scene Generator (Phase 1)")
16
  st.write(
17
  """
18
- Paste a short story, and this app will break it into **cinematic scenes** with:
19
- - Scene title
20
- - Setting & mood
21
- - Characters
22
- - Short summary
23
- - A detailed **visual prompt** (for future image generation)
24
  """
25
  )
26
 
27
  # =========================
28
- # 2. LOAD LLM (FLAN-T5) - CACHED
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  # =========================
30
 
31
  @st.cache_resource
32
  def load_scene_model():
33
- model_name = "google/flan-t5-base" # good starting point, can upgrade later
34
  tokenizer = AutoTokenizer.from_pretrained(model_name)
35
  model = AutoModelForSeq2SeqLM.from_pretrained(model_name)
36
  return tokenizer, model
37
 
 
38
  tokenizer, scene_model = load_scene_model()
39
 
40
 
@@ -55,7 +87,7 @@ def generate_text(prompt: str, max_new_tokens: int = 256) -> str:
55
 
56
 
57
  # =========================
58
- # 3. STORY β†’ CHUNKS β†’ SCENES LOGIC
59
  # =========================
60
 
61
  def split_story_into_chunks(story_text: str, max_chars_per_chunk: int = 600):
@@ -138,7 +170,52 @@ def story_to_scenes(story_text: str):
138
 
139
 
140
  # =========================
141
- # 4. STREAMLIT UI
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  # =========================
143
 
144
  st.subheader("πŸ“ Paste Your Story")
@@ -159,32 +236,59 @@ story_text = st.text_area(
159
  height=260
160
  )
161
 
162
- if st.button("🎬 Generate Scenes"):
 
 
 
 
 
163
  if not story_text.strip():
164
  st.error("Please paste a story first.")
165
  else:
166
  with st.spinner("Breaking story into scenes..."):
167
  scenes = story_to_scenes(story_text)
168
-
169
  st.success(f"Generated {len(scenes)} scene(s).")
170
 
171
- st.markdown("---")
172
- st.subheader("πŸ“š Generated Scenes")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
 
174
- for scene in scenes:
175
- scene_id = scene.get("scene_id", "?")
176
- title = scene.get("title", f"Scene {scene_id}")
177
- with st.expander(f"Scene {scene_id}: {title}", expanded=True):
178
- st.markdown(f"**Setting:** {scene.get('setting', '')}")
179
- st.markdown(f"**Mood:** {scene.get('mood', '')}")
180
- st.markdown(f"**Characters:** {', '.join(scene.get('characters', [])) or 'N/A'}")
181
 
182
- st.markdown("**Summary:**")
183
- st.write(scene.get("summary", ""))
184
 
185
- st.markdown("**Visual Prompt (for future image generation):**")
186
- st.code(textwrap.fill(scene.get("visual_prompt", ""), width=90), language="text")
 
 
 
 
 
 
187
 
188
- st.info("βœ… Phase 1 complete: story β†’ structured scenes.\n\nNext phases will turn these visual prompts into images and then a video.")
189
  else:
190
  st.info("Paste a story and click **Generate Scenes** to begin.")
 
1
  import streamlit as st
2
  from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
3
+ from diffusers import StableDiffusionPipeline
4
+ import torch
5
  import json
6
  import textwrap
7
 
 
14
  layout="wide"
15
  )
16
 
17
+ st.title("🎬 AI Story β†’ Movie Scene Generator")
18
  st.write(
19
  """
20
+ Paste a short story, and this app will:
21
+ 1. Break it into **cinematic scenes** (title, setting, characters, mood, summary).
22
+ 2. Generate a **visual prompt** for each scene.
23
+ 3. Turn prompts into **AI images** in either:
24
+ - πŸ§ͺ Anime-style visuals
25
+ - πŸŽ₯ Realistic cinematic visuals
26
  """
27
  )
28
 
29
  # =========================
30
+ # 2. SIDEBAR: VISUAL STYLE
31
+ # =========================
32
+ st.sidebar.header("Visual Style Settings")
33
+ style = st.sidebar.selectbox(
34
+ "Choose visual style for images:",
35
+ ["Anime", "Cinematic Realistic"]
36
+ )
37
+
38
+
39
+ def build_styled_prompt(base_prompt: str, style: str) -> str:
40
+ """
41
+ Take the base visual prompt from the scene and inject style instructions.
42
+ """
43
+ base_prompt = base_prompt.strip()
44
+ if style == "Anime":
45
+ return (
46
+ base_prompt +
47
+ ", anime style, detailed 2D illustration, clean line art, vibrant colors, "
48
+ "studio anime, keyframe, sharp focus, highly detailed, dramatic lighting"
49
+ )
50
+ else: # Cinematic Realistic
51
+ return (
52
+ base_prompt +
53
+ ", ultra realistic, cinematic lighting, 35mm film, depth of field, 4k, "
54
+ "high detail, dramatic shadows, film still, volumetric light, highly detailed"
55
+ )
56
+
57
+
58
+ # =========================
59
+ # 3. LOAD LLM (FLAN-T5) - CACHED
60
  # =========================
61
 
62
  @st.cache_resource
63
  def load_scene_model():
64
+ model_name = "google/flan-t5-base" # good starting point; can upgrade to -large later
65
  tokenizer = AutoTokenizer.from_pretrained(model_name)
66
  model = AutoModelForSeq2SeqLM.from_pretrained(model_name)
67
  return tokenizer, model
68
 
69
+
70
  tokenizer, scene_model = load_scene_model()
71
 
72
 
 
87
 
88
 
89
  # =========================
90
+ # 4. STORY β†’ CHUNKS β†’ SCENES LOGIC
91
  # =========================
92
 
93
  def split_story_into_chunks(story_text: str, max_chars_per_chunk: int = 600):
 
170
 
171
 
172
  # =========================
173
+ # 5. LOAD STABLE DIFFUSION PIPELINE (IMAGE MODEL)
174
+ # =========================
175
+
176
+ @st.cache_resource
177
+ def load_image_model():
178
+ """
179
+ Load Stable Diffusion pipeline for image generation.
180
+ Uses CPU on Spaces by default; will use GPU if available.
181
+ """
182
+ model_id = "runwayml/stable-diffusion-v1-5"
183
+
184
+ if torch.cuda.is_available():
185
+ dtype = torch.float16
186
+ else:
187
+ dtype = torch.float32
188
+
189
+ pipe = StableDiffusionPipeline.from_pretrained(
190
+ model_id,
191
+ torch_dtype=dtype,
192
+ safety_checker=None # can be customized if needed
193
+ )
194
+
195
+ if torch.cuda.is_available():
196
+ pipe = pipe.to("cuda")
197
+ else:
198
+ pipe = pipe.to("cpu")
199
+
200
+ return pipe
201
+
202
+
203
+ def generate_scene_image(prompt: str):
204
+ """
205
+ Generate a single image from a text prompt using Stable Diffusion.
206
+ """
207
+ pipe = load_image_model()
208
+ # You can tweak num_inference_steps and guidance_scale for quality/speed tradeoff
209
+ image = pipe(
210
+ prompt,
211
+ num_inference_steps=25,
212
+ guidance_scale=7.5
213
+ ).images[0]
214
+ return image
215
+
216
+
217
+ # =========================
218
+ # 6. STREAMLIT UI
219
  # =========================
220
 
221
  st.subheader("πŸ“ Paste Your Story")
 
236
  height=260
237
  )
238
 
239
+ generate_clicked = st.button("🎬 Generate Scenes")
240
+
241
+ if "scenes" not in st.session_state:
242
+ st.session_state["scenes"] = None
243
+
244
+ if generate_clicked:
245
  if not story_text.strip():
246
  st.error("Please paste a story first.")
247
  else:
248
  with st.spinner("Breaking story into scenes..."):
249
  scenes = story_to_scenes(story_text)
250
+ st.session_state["scenes"] = scenes
251
  st.success(f"Generated {len(scenes)} scene(s).")
252
 
253
+ scenes = st.session_state.get("scenes", None)
254
+
255
+ if scenes:
256
+ st.markdown("---")
257
+ st.subheader("πŸ“š Generated Scenes & Visuals")
258
+
259
+ for scene in scenes:
260
+ scene_id = scene.get("scene_id", "?")
261
+ title = scene.get("title", f"Scene {scene_id}")
262
+ setting = scene.get("setting", "")
263
+ mood = scene.get("mood", "")
264
+ characters = scene.get("characters", [])
265
+ summary = scene.get("summary", "")
266
+ base_prompt = scene.get("visual_prompt", "")
267
+
268
+ styled_prompt = build_styled_prompt(base_prompt, style)
269
+
270
+ with st.expander(f"Scene {scene_id}: {title}", expanded=True):
271
+ st.markdown(f"**Setting:** {setting}")
272
+ st.markdown(f"**Mood:** {mood}")
273
+ st.markdown(f"**Characters:** {', '.join(characters) or 'N/A'}")
274
+
275
+ st.markdown("**Summary:**")
276
+ st.write(summary)
277
 
278
+ st.markdown("**Base Visual Prompt:**")
279
+ st.code(textwrap.fill(base_prompt, width=90), language="text")
 
 
 
 
 
280
 
281
+ st.markdown(f"**Styled Prompt for {style} Image:**")
282
+ st.code(textwrap.fill(styled_prompt, width=90), language="text")
283
 
284
+ img_btn = st.button(
285
+ f"πŸ–Ό Generate {style} Image for Scene {scene_id}",
286
+ key=f"img_btn_{scene_id}"
287
+ )
288
+ if img_btn:
289
+ with st.spinner("Generating image... This may take some time."):
290
+ img = generate_scene_image(styled_prompt)
291
+ st.image(img, caption=f"Scene {scene_id} – {title} ({style})", use_column_width=True)
292
 
 
293
  else:
294
  st.info("Paste a story and click **Generate Scenes** to begin.")