moose commited on
Commit
b333e18
·
1 Parent(s): c47a9b9

routine commit

Browse files
Files changed (2) hide show
  1. CLAUDE.md +6 -21
  2. app.py +7 -334
CLAUDE.md CHANGED
@@ -10,7 +10,6 @@ This is a Gradio Space that implements "Next Scene" cinematic image generation u
10
  - Base model: `Qwen/Qwen-Image-Edit-2509` (image editing diffusion model)
11
  - Accelerated transformer: `linoyts/Qwen-Image-Edit-Rapid-AIO` (4-step optimized variant)
12
  - LoRA adapter: `lovis93/next-scene-qwen-image-lora-2509` (cinematic progression fine-tune)
13
- - Text encoder: `Qwen2.5-VL-72B-Instruct` (via Hugging Face InferenceClient for prompt enhancement)
14
 
15
  ## Running the Application
16
 
@@ -32,8 +31,7 @@ The app requires GPU access. It uses the `@spaces.GPU` decorator for Hugging Fac
32
 
33
  1. **Input Processing** (`app.py:infer`):
34
  - Accepts input images via Gradio Gallery (filepath-based)
35
- - Optional prompt rewriting using `Qwen2.5-VL-72B-Instruct` API
36
- - Automatic "Next Scene" prompt generation from images
37
 
38
  2. **Image Generation** (`qwenimage/pipeline_qwenimage_edit_plus.py`):
39
  - Custom pipeline extending `DiffusionPipeline`
@@ -68,21 +66,9 @@ The app requires GPU access. It uses the `@spaces.GPU` decorator for Hugging Fac
68
  - Dual-stream attention with rotary embeddings
69
  - Cache contexts for conditional/unconditional forward passes
70
 
71
- ### Prompt Engineering
72
 
73
- **Two-stage prompt system:**
74
-
75
- 1. **Edit Instruction Rewriter** (`SYSTEM_PROMPT`):
76
- - Normalizes user prompts into professional editing instructions
77
- - Handles text replacement (requires quotes), object manipulation, style transfer
78
- - Used when `rewrite_prompt=True` checkbox is enabled
79
-
80
- 2. **Next Scene Generator** (`NEXT_SCENE_SYSTEM_PROMPT`):
81
- - Automatically suggests cinematic camera movements
82
- - Focus on visual progression (dolly, pan, zoom, framing changes)
83
- - Auto-triggers when input images change
84
-
85
- Both use `Qwen2.5-VL-72B-Instruct` via Hugging Face InferenceClient with Nebius provider. Requires `HF_TOKEN` environment variable.
86
 
87
  ## Important Implementation Details
88
 
@@ -120,7 +106,7 @@ Input/output galleries use `type="filepath"` (string paths) rather than PIL Imag
120
 
121
  ## Environment Variables
122
 
123
- - `HF_TOKEN` - Required for Qwen2.5-VL API access (prompt rewriting/generation)
124
 
125
  ## File Outputs
126
 
@@ -146,19 +132,18 @@ from gradio_client import Client, handle_file
146
  client = Client("Sneak-Moose/Qwen-Image-Edit-next-scene")
147
  result = client.predict(
148
  images=[],
149
- prompt="Next Scene: Camera dollies forward...",
150
  seed=42,
151
  randomize_seed=False,
152
  true_guidance_scale=1.0,
153
  num_inference_steps=4,
154
  height=1024,
155
  width=1024,
156
- rewrite_prompt=False,
157
  api_name="/infer"
158
  )
159
  ```
160
 
161
- The `custom/API_GUIDE.txt` contains full documentation of all available endpoints including `/infer`, `/turn_into_video`, `/suggest_next_scene_prompt`, and utility functions.
162
 
163
  ## Development Notes
164
 
 
10
  - Base model: `Qwen/Qwen-Image-Edit-2509` (image editing diffusion model)
11
  - Accelerated transformer: `linoyts/Qwen-Image-Edit-Rapid-AIO` (4-step optimized variant)
12
  - LoRA adapter: `lovis93/next-scene-qwen-image-lora-2509` (cinematic progression fine-tune)
 
13
 
14
  ## Running the Application
15
 
 
31
 
32
  1. **Input Processing** (`app.py:infer`):
33
  - Accepts input images via Gradio Gallery (filepath-based)
34
+ - Uses user-provided prompts directly without modification
 
35
 
36
  2. **Image Generation** (`qwenimage/pipeline_qwenimage_edit_plus.py`):
37
  - Custom pipeline extending `DiffusionPipeline`
 
66
  - Dual-stream attention with rotary embeddings
67
  - Cache contexts for conditional/unconditional forward passes
68
 
69
+ ### Prompt Handling
70
 
71
+ The application uses user-provided prompts directly without any preprocessing, rewriting, or AI-based enhancement. Users have full control over the exact prompt text that gets passed to the diffusion model.
 
 
 
 
 
 
 
 
 
 
 
 
72
 
73
  ## Important Implementation Details
74
 
 
106
 
107
  ## Environment Variables
108
 
109
+ No environment variables are required for basic operation. The application runs entirely with local models.
110
 
111
  ## File Outputs
112
 
 
132
  client = Client("Sneak-Moose/Qwen-Image-Edit-next-scene")
133
  result = client.predict(
134
  images=[],
135
+ prompt="Camera dollies forward, revealing more of the scene",
136
  seed=42,
137
  randomize_seed=False,
138
  true_guidance_scale=1.0,
139
  num_inference_steps=4,
140
  height=1024,
141
  width=1024,
 
142
  api_name="/infer"
143
  )
144
  ```
145
 
146
+ The `custom/API_GUIDE.txt` contains full documentation of all available endpoints including `/infer`, `/turn_into_video`, and utility functions.
147
 
148
  ## Development Notes
149
 
app.py CHANGED
@@ -11,15 +11,11 @@ from qwenimage.pipeline_qwenimage_edit_plus import QwenImageEditPlusPipeline
11
  from qwenimage.transformer_qwenimage import QwenImageTransformer2DModel
12
  from qwenimage.qwen_fa3_processor import QwenDoubleStreamAttnProcessorFA3
13
 
14
- from huggingface_hub import InferenceClient
15
  import math
16
  from huggingface_hub import hf_hub_download
17
  from safetensors.torch import load_file
18
 
19
  import os
20
- import base64
21
- from io import BytesIO
22
- import json
23
  import time # Added for history update delay
24
 
25
  from gradio_client import Client, handle_file
@@ -72,286 +68,6 @@ def turn_into_video(input_images, output_images, prompt, progress=gr.Progress(tr
72
  return video_path['video']
73
 
74
 
75
-
76
-
77
- SYSTEM_PROMPT = '''
78
- # Edit Instruction Rewriter
79
- You are a professional edit instruction rewriter. Your task is to generate a precise, concise, and visually achievable professional-level edit instruction based on the user-provided instruction and the image to be edited.
80
- Please strictly follow the rewriting rules below:
81
- ## 1. General Principles
82
- - Keep the rewritten prompt **concise and comprehensive**. Avoid overly long sentences and unnecessary descriptive language.
83
- - If the instruction is contradictory, vague, or unachievable, prioritize reasonable inference and correction, and supplement details when necessary.
84
- - Keep the main part of the original instruction unchanged, only enhancing its clarity, rationality, and visual feasibility.
85
- - All added objects or modifications must align with the logic and style of the scene in the input images.
86
- - If multiple sub-images are to be generated, describe the content of each sub-image individually.
87
- ## 2. Task-Type Handling Rules
88
- ### 1. Add, Delete, Replace Tasks
89
- - If the instruction is clear (already includes task type, target entity, position, quantity, attributes), preserve the original intent and only refine the grammar.
90
- - If the description is vague, supplement with minimal but sufficient details (category, color, size, orientation, position, etc.). For example:
91
- > Original: "Add an animal"
92
- > Rewritten: "Add a light-gray cat in the bottom-right corner, sitting and facing the camera"
93
- - Remove meaningless instructions: e.g., "Add 0 objects" should be ignored or flagged as invalid.
94
- - For replacement tasks, specify "Replace Y with X" and briefly describe the key visual features of X.
95
- ### 2. Text Editing Tasks
96
- - All text content must be enclosed in English double quotes `" "`. Keep the original language of the text, and keep the capitalization.
97
- - Both adding new text and replacing existing text are text replacement tasks, For example:
98
- - Replace "xx" to "yy"
99
- - Replace the mask / bounding box to "yy"
100
- - Replace the visual object to "yy"
101
- - Specify text position, color, and layout only if user has required.
102
- - If font is specified, keep the original language of the font.
103
- ### 3. Human Editing Tasks
104
- - Make the smallest changes to the given user's prompt.
105
- - If changes to background, action, expression, camera shot, or ambient lighting are required, please list each modification individually.
106
- - **Edits to makeup or facial features / expression must be subtle, not exaggerated, and must preserve the subject's identity consistency.**
107
- > Original: "Add eyebrows to the face"
108
- > Rewritten: "Slightly thicken the person's eyebrows with little change, look natural."
109
- ### 4. Style Conversion or Enhancement Tasks
110
- - If a style is specified, describe it concisely using key visual features. For example:
111
- > Original: "Disco style"
112
- > Rewritten: "1970s disco style: flashing lights, disco ball, mirrored walls, vibrant colors"
113
- - For style reference, analyze the original image and extract key characteristics (color, composition, texture, lighting, artistic style, etc.), integrating them into the instruction.
114
- - **Colorization tasks (including old photo restoration) must use the fixed template:**
115
- "Restore and colorize the old photo."
116
- - Clearly specify the object to be modified. For example:
117
- > Original: Modify the subject in Picture 1 to match the style of Picture 2.
118
- > Rewritten: Change the girl in Picture 1 to the ink-wash style of Picture 2 — rendered in black-and-white watercolor with soft color transitions.
119
- ### 5. Material Replacement
120
- - Clearly specify the object and the material. For example: "Change the material of the apple to papercut style."
121
- - For text material replacement, use the fixed template:
122
- "Change the material of text "xxxx" to laser style"
123
- ### 6. Logo/Pattern Editing
124
- - Material replacement should preserve the original shape and structure as much as possible. For example:
125
- > Original: "Convert to sapphire material"
126
- > Rewritten: "Convert the main subject in the image to sapphire material, preserving similar shape and structure"
127
- - When migrating logos/patterns to new scenes, ensure shape and structure consistency. For example:
128
- > Original: "Migrate the logo in the image to a new scene"
129
- > Rewritten: "Migrate the logo in the image to a new scene, preserving similar shape and structure"
130
- ### 7. Multi-Image Tasks
131
- - Rewritten prompts must clearly point out which image's element is being modified. For example:
132
- > Original: "Replace the subject of picture 1 with the subject of picture 2"
133
- > Rewritten: "Replace the girl of picture 1 with the boy of picture 2, keeping picture 2's background unchanged"
134
- - For stylization tasks, describe the reference image's style in the rewritten prompt, while preserving the visual content of the source image.
135
- ## 3. Rationale and Logic Check
136
- - Resolve contradictory instructions: e.g., "Remove all trees but keep all trees" requires logical correction.
137
- - Supplement missing critical information: e.g., if position is unspecified, choose a reasonable area based on composition (near subject, blank space, center/edge, etc.).
138
- # Output Format Example
139
- ```json
140
- {
141
- "Rewritten": "..."
142
- }
143
- '''
144
-
145
-
146
- NEXT_SCENE_SYSTEM_PROMPT = '''
147
- # Next Scene Prompt Generator
148
- You are a cinematic AI director assistant. Your task is to analyze the provided image and generate a compelling "Next Scene" prompt that describes the natural cinematic progression from the current frame.
149
- ## Core Principles:
150
- - Think like a film director: Consider camera dynamics, visual composition, and narrative continuity
151
- - Create prompts that flow seamlessly from the current frame
152
- - Focus on **visual progression** rather than static modifications
153
- - Maintain compositional coherence while introducing organic transitions
154
- ## Prompt Structure:
155
- Always begin with "Next Scene: " followed by your cinematic description.
156
- ## Key Elements to Include:
157
- 1. **Camera Movement**: Specify one of these or combinations:
158
- - Dolly shots (camera moves toward/away from subject)
159
- - Push-ins or pull-backs
160
- - Tracking moves (camera follows subject)
161
- - Pan left/right
162
- - Tilt up/down
163
- - Zoom in/out
164
- 2. **Framing Evolution**: Describe how the shot composition changes:
165
- - Wide to close-up transitions
166
- - Angle shifts (high angle to eye level, etc.)
167
- - Reframing of subjects
168
- - Revealing new elements in frame
169
- 3. **Environmental Reveals** (if applicable):
170
- - New characters entering frame
171
- - Expanded scenery
172
- - Spatial progression
173
- - Background elements becoming visible
174
- 4. **Atmospheric Shifts** (if enhancing the scene):
175
- - Lighting changes (golden hour, shadows, lens flare)
176
- - Weather evolution
177
- - Time-of-day transitions
178
- - Depth and mood indicators
179
- ## Guidelines:
180
- - Keep descriptions concise but vivid (2-3 sentences max)
181
- - Always specify the camera action first
182
- - Focus on what changes between this frame and the next
183
- - Maintain the scene's existing style and mood unless intentionally transitioning
184
- - Prefer natural, organic progressions over abrupt changes
185
- ## Example Outputs:
186
- - "Next Scene: The camera pulls back from a tight close-up on the airship to a sweeping aerial view, revealing an entire fleet of vessels soaring through a fantasy landscape."
187
- - "Next Scene: The camera tracks forward and tilts down, bringing the sun and helicopters closer into frame as a strong lens flare intensifies."
188
- - "Next Scene: The camera pans right, removing the dragon and rider from view while revealing more of the floating mountain range in the distance."
189
- - "Next Scene: The camera moves slightly forward as sunlight breaks through the clouds, casting a soft glow around the character's silhouette in the mist. Realistic cinematic style, atmospheric depth."
190
- ## Output Format:
191
- Return ONLY the next scene prompt as plain text, starting with "Next Scene: "
192
- Do NOT include JSON formatting or additional explanations.
193
- '''
194
-
195
- # --- Prompt Enhancement using Hugging Face InferenceClient ---
196
- def polish_prompt_hf(original_prompt, img_list):
197
- """
198
- Rewrites the prompt using a Hugging Face InferenceClient.
199
- """
200
- # Ensure HF_TOKEN is set
201
- api_key = os.environ.get("HF_TOKEN")
202
- if not api_key:
203
- print("Warning: HF_TOKEN not set. Falling back to original prompt.")
204
- return original_prompt
205
-
206
- try:
207
- # Initialize the client
208
- prompt = f"{SYSTEM_PROMPT}\n\nUser Input: {original_prompt}\n\nRewritten Prompt:"
209
- client = InferenceClient(
210
- provider="nebius",
211
- api_key=api_key,
212
- )
213
-
214
- # Format the messages for the chat completions API
215
- sys_promot = "you are a helpful assistant, you should provide useful answers to users."
216
- messages = [
217
- {"role": "system", "content": sys_promot},
218
- {"role": "user", "content": []}]
219
- for img in img_list:
220
- messages[1]["content"].append(
221
- {"image": f"data:image/png;base64,{encode_image(img)}"})
222
- messages[1]["content"].append({"text": f"{prompt}"})
223
-
224
- # Call the API
225
- completion = client.chat.completions.create(
226
- model="Qwen/Qwen2.5-VL-72B-Instruct",
227
- messages=messages,
228
- )
229
-
230
- # Parse the response
231
- result = completion.choices[0].message.content
232
-
233
- # Try to extract JSON if present
234
- if '"Rewritten"' in result:
235
- try:
236
- # Clean up the response
237
- result = result.replace('```json', '').replace('```', '')
238
- result_json = json.loads(result)
239
- polished_prompt = result_json.get('Rewritten', result)
240
- except:
241
- polished_prompt = result
242
- else:
243
- polished_prompt = result
244
-
245
- polished_prompt = polished_prompt.strip().replace("\n", " ")
246
- return polished_prompt
247
-
248
- except Exception as e:
249
- print(f"Error during API call to Hugging Face: {e}")
250
- # Fallback to original prompt if enhancement fails
251
- return original_prompt
252
-
253
- def next_scene_prompt(original_prompt, img_list):
254
- """
255
- Rewrites the prompt using a Hugging Face InferenceClient.
256
- Supports multiple images via img_list.
257
- """
258
- # Ensure HF_TOKEN is set
259
- api_key = os.environ.get("HF_TOKEN")
260
- if not api_key:
261
- print("Warning: HF_TOKEN not set. Falling back to original prompt.")
262
- return original_prompt
263
- prompt = f"{NEXT_SCENE_SYSTEM_PROMPT}"
264
- system_prompt = "you are a helpful assistant, you should provide useful answers to users."
265
- try:
266
- # Initialize the client
267
- client = InferenceClient(
268
- provider="nebius",
269
- api_key=api_key,
270
- )
271
-
272
- # Convert list of images to base64 data URLs
273
- image_urls = []
274
- if img_list is not None:
275
- # Ensure img_list is actually a list
276
- if not isinstance(img_list, list):
277
- img_list = [img_list]
278
-
279
- for img in img_list:
280
- image_url = None
281
- # If img is a PIL Image
282
- if hasattr(img, 'save'): # Check if it's a PIL Image
283
- buffered = BytesIO()
284
- img.save(buffered, format="PNG")
285
- img_base64 = base64.b64encode(buffered.getvalue()).decode('utf-8')
286
- image_url = f"data:image/png;base64,{img_base64}"
287
- # If img is already a file path (string)
288
- elif isinstance(img, str):
289
- with open(img, "rb") as image_file:
290
- img_base64 = base64.b64encode(image_file.read()).decode('utf-8')
291
- image_url = f"data:image/png;base64,{img_base64}"
292
- else:
293
- print(f"Warning: Unexpected image type: {type(img)}, skipping...")
294
- continue
295
-
296
- if image_url:
297
- image_urls.append(image_url)
298
-
299
- # Build the content array with text first, then all images
300
- content = [
301
- {
302
- "type": "text",
303
- "text": prompt
304
- }
305
- ]
306
-
307
- # Add all images to the content
308
- for image_url in image_urls:
309
- content.append({
310
- "type": "image_url",
311
- "image_url": {
312
- "url": image_url
313
- }
314
- })
315
-
316
- # Format the messages for the chat completions API
317
- messages = [
318
- {"role": "system", "content": system_prompt},
319
- {
320
- "role": "user",
321
- "content": content
322
- }
323
- ]
324
-
325
- # Call the API
326
- completion = client.chat.completions.create(
327
- model="Qwen/Qwen2.5-VL-72B-Instruct",
328
- messages=messages,
329
- )
330
-
331
- # Parse the response
332
- result = completion.choices[0].message.content
333
-
334
- # Try to extract JSON if present
335
- if '"Rewritten"' in result:
336
- try:
337
- # Clean up the response
338
- result = result.replace('```json', '').replace('```', '')
339
- result_json = json.loads(result)
340
- polished_prompt = result_json.get('Rewritten', result)
341
- except:
342
- polished_prompt = result
343
- else:
344
- polished_prompt = result
345
-
346
- polished_prompt = polished_prompt.strip().replace("\n", " ")
347
- return polished_prompt
348
-
349
- except Exception as e:
350
- print(f"Error during API call to Hugging Face: {e}")
351
- # Fallback to original prompt if enhancement fails
352
- return original_prompt
353
-
354
-
355
  def update_history(new_images, history):
356
  """Updates the history gallery with the new images."""
357
  time.sleep(0.5) # Small delay to ensure images are ready
@@ -371,12 +87,6 @@ def use_history_as_input(evt: gr.SelectData):
371
  # For filepath gallery, return the path directly in a list
372
  return gr.update(value=[evt.value])
373
  return gr.update()
374
-
375
- def encode_image(pil_image):
376
- import io
377
- buffered = io.BytesIO()
378
- pil_image.save(buffered, format="PNG")
379
- return base64.b64encode(buffered.getvalue()).decode("utf-8")
380
 
381
  # --- Model Loading ---
382
  dtype = torch.bfloat16
@@ -413,33 +123,6 @@ def use_output_as_input(output_images):
413
  return []
414
  return output_images
415
 
416
- def suggest_next_scene_prompt(images):
417
- pil_images = []
418
- if images is not None:
419
- for item in images:
420
- try:
421
- if isinstance(item, str):
422
- # Direct file path from filepath gallery
423
- pil_images.append(Image.open(item).convert("RGB"))
424
- elif isinstance(item, tuple) and len(item) > 0:
425
- # Tuple format (legacy support)
426
- if isinstance(item[0], Image.Image):
427
- pil_images.append(item[0].convert("RGB"))
428
- elif isinstance(item[0], str):
429
- pil_images.append(Image.open(item[0]).convert("RGB"))
430
- elif isinstance(item, Image.Image):
431
- pil_images.append(item.convert("RGB"))
432
- elif hasattr(item, "name"):
433
- pil_images.append(Image.open(item.name).convert("RGB"))
434
- except Exception:
435
- continue
436
- if len(pil_images) > 0:
437
- prompt = next_scene_prompt("", pil_images)
438
- else:
439
- prompt = ""
440
- print("next scene prompt: ", prompt)
441
- return prompt
442
-
443
  # --- Main Inference Function (with hardcoded negative prompt) ---
444
  @spaces.GPU(duration=300)
445
  def infer(
@@ -451,7 +134,6 @@ def infer(
451
  num_inference_steps=4,
452
  height=None,
453
  width=None,
454
- rewrite_prompt=True,
455
  num_images_per_prompt=1,
456
  progress=gr.Progress(track_tqdm=True),
457
  ):
@@ -460,13 +142,13 @@ def infer(
460
  """
461
  # Hardcode the negative prompt as requested
462
  negative_prompt = " "
463
-
464
  if randomize_seed:
465
  seed = random.randint(0, MAX_SEED)
466
 
467
  # Set up the generator for reproducibility
468
  generator = torch.Generator(device=device).manual_seed(seed)
469
-
470
  # Load input images into PIL Images
471
  pil_images = []
472
  if images is not None:
@@ -493,10 +175,6 @@ def infer(
493
  print(f"Calling pipeline with prompt: '{prompt}'")
494
  print(f"Negative Prompt: '{negative_prompt}'")
495
  print(f"Seed: {seed}, Steps: {num_inference_steps}, Guidance: {true_guidance_scale}, Size: {width}x{height}")
496
- if rewrite_prompt and len(pil_images) > 0:
497
- prompt = polish_prompt_hf(prompt, pil_images)
498
- print(f"Rewritten Prompt: {prompt}")
499
-
500
 
501
  # Generate the image
502
  images_pil = pipe(
@@ -547,8 +225,9 @@ with gr.Blocks(css=css) as demo:
547
  </div>
548
  """)
549
  gr.Markdown("""
550
- This demo uses the new [Qwen-Image-Edit-2509](https://huggingface.co/Qwen/Qwen-Image-Edit-2509) with [lovis93/next-scene-qwen-image-lora](https://huggingface.co/lovis93/next-scene-qwen-image-lora-2509) for cinematic image sequences with natural visual progression from frame to frame 🎥 and [Phr00t/Qwen-Image-Edit-Rapid-AIO](https://huggingface.co/Phr00t/Qwen-Image-Edit-Rapid-AIO/tree/main) + [AoT compilation & FA3](https://huggingface.co/blog/zerogpu-aoti) for accelerated 4-step inference.
551
- Try on [Qwen Chat](https://chat.qwen.ai/), or [download model](https://huggingface.co/Qwen/Qwen-Image-Edit-2509) to run locally with ComfyUI or diffusers.
 
552
  """)
553
  with gr.Row():
554
  with gr.Column():
@@ -560,7 +239,7 @@ with gr.Blocks(css=css) as demo:
560
  prompt = gr.Text(
561
  label="Prompt 🪄",
562
  show_label=True,
563
- placeholder="Next scene: The camera dollies in to a tight close-up...",
564
  )
565
  run_button = gr.Button("Edit!", variant="primary")
566
 
@@ -610,11 +289,8 @@ with gr.Blocks(css=css) as demo:
610
  step=8,
611
  value=None,
612
  )
613
-
614
-
615
- rewrite_prompt = gr.Checkbox(label="Rewrite prompt", value=False)
616
 
617
-
618
 
619
  with gr.Column():
620
  result = gr.Gallery(label="Result", show_label=False, type="filepath")
@@ -650,7 +326,6 @@ with gr.Blocks(css=css) as demo:
650
  num_inference_steps,
651
  height,
652
  width,
653
- rewrite_prompt,
654
  ],
655
  outputs=[result, seed, use_output_btn, turn_video_btn],
656
 
@@ -683,8 +358,6 @@ with gr.Blocks(css=css) as demo:
683
 
684
  )
685
 
686
- input_images.change(fn=suggest_next_scene_prompt, inputs=[input_images], outputs=[prompt])
687
-
688
  turn_video_btn.click(
689
  fn=lambda: gr.update(visible=True),
690
  inputs=None,
 
11
  from qwenimage.transformer_qwenimage import QwenImageTransformer2DModel
12
  from qwenimage.qwen_fa3_processor import QwenDoubleStreamAttnProcessorFA3
13
 
 
14
  import math
15
  from huggingface_hub import hf_hub_download
16
  from safetensors.torch import load_file
17
 
18
  import os
 
 
 
19
  import time # Added for history update delay
20
 
21
  from gradio_client import Client, handle_file
 
68
  return video_path['video']
69
 
70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  def update_history(new_images, history):
72
  """Updates the history gallery with the new images."""
73
  time.sleep(0.5) # Small delay to ensure images are ready
 
87
  # For filepath gallery, return the path directly in a list
88
  return gr.update(value=[evt.value])
89
  return gr.update()
 
 
 
 
 
 
90
 
91
  # --- Model Loading ---
92
  dtype = torch.bfloat16
 
123
  return []
124
  return output_images
125
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  # --- Main Inference Function (with hardcoded negative prompt) ---
127
  @spaces.GPU(duration=300)
128
  def infer(
 
134
  num_inference_steps=4,
135
  height=None,
136
  width=None,
 
137
  num_images_per_prompt=1,
138
  progress=gr.Progress(track_tqdm=True),
139
  ):
 
142
  """
143
  # Hardcode the negative prompt as requested
144
  negative_prompt = " "
145
+
146
  if randomize_seed:
147
  seed = random.randint(0, MAX_SEED)
148
 
149
  # Set up the generator for reproducibility
150
  generator = torch.Generator(device=device).manual_seed(seed)
151
+
152
  # Load input images into PIL Images
153
  pil_images = []
154
  if images is not None:
 
175
  print(f"Calling pipeline with prompt: '{prompt}'")
176
  print(f"Negative Prompt: '{negative_prompt}'")
177
  print(f"Seed: {seed}, Steps: {num_inference_steps}, Guidance: {true_guidance_scale}, Size: {width}x{height}")
 
 
 
 
178
 
179
  # Generate the image
180
  images_pil = pipe(
 
225
  </div>
226
  """)
227
  gr.Markdown("""
228
+ This demo uses [Qwen-Image-Edit-2509](https://huggingface.co/Qwen/Qwen-Image-Edit-2509) with [lovis93/next-scene-qwen-image-lora](https://huggingface.co/lovis93/next-scene-qwen-image-lora-2509) for cinematic image sequences with natural visual progression from frame to frame 🎥 and [Phr00t/Qwen-Image-Edit-Rapid-AIO](https://huggingface.co/Phr00t/Qwen-Image-Edit-Rapid-AIO/tree/main) + [AoT compilation & FA3](https://huggingface.co/blog/zerogpu-aoti) for accelerated 4-step inference.
229
+
230
+ Upload an image and enter your prompt to generate the next scene. The model will use your prompt exactly as provided.
231
  """)
232
  with gr.Row():
233
  with gr.Column():
 
239
  prompt = gr.Text(
240
  label="Prompt 🪄",
241
  show_label=True,
242
+ placeholder="Enter your prompt here...",
243
  )
244
  run_button = gr.Button("Edit!", variant="primary")
245
 
 
289
  step=8,
290
  value=None,
291
  )
 
 
 
292
 
293
+
294
 
295
  with gr.Column():
296
  result = gr.Gallery(label="Result", show_label=False, type="filepath")
 
326
  num_inference_steps,
327
  height,
328
  width,
 
329
  ],
330
  outputs=[result, seed, use_output_btn, turn_video_btn],
331
 
 
358
 
359
  )
360
 
 
 
361
  turn_video_btn.click(
362
  fn=lambda: gr.update(visible=True),
363
  inputs=None,