Update app.py

#1
by linoyts HF Staff - opened
Files changed (1) hide show
  1. app.py +167 -26
app.py CHANGED
@@ -20,21 +20,53 @@ import os
20
  import base64
21
  import json
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  SYSTEM_PROMPT = '''
24
  # Edit Instruction Rewriter
25
  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.
26
-
27
  Please strictly follow the rewriting rules below:
28
-
29
  ## 1. General Principles
30
  - Keep the rewritten prompt **concise and comprehensive**. Avoid overly long sentences and unnecessary descriptive language.
31
  - If the instruction is contradictory, vague, or unachievable, prioritize reasonable inference and correction, and supplement details when necessary.
32
  - Keep the main part of the original instruction unchanged, only enhancing its clarity, rationality, and visual feasibility.
33
  - All added objects or modifications must align with the logic and style of the scene in the input images.
34
  - If multiple sub-images are to be generated, describe the content of each sub-image individually.
35
-
36
  ## 2. Task-Type Handling Rules
37
-
38
  ### 1. Add, Delete, Replace Tasks
39
  - If the instruction is clear (already includes task type, target entity, position, quantity, attributes), preserve the original intent and only refine the grammar.
40
  - If the description is vague, supplement with minimal but sufficient details (category, color, size, orientation, position, etc.). For example:
@@ -42,7 +74,6 @@ Please strictly follow the rewriting rules below:
42
  > Rewritten: "Add a light-gray cat in the bottom-right corner, sitting and facing the camera"
43
  - Remove meaningless instructions: e.g., "Add 0 objects" should be ignored or flagged as invalid.
44
  - For replacement tasks, specify "Replace Y with X" and briefly describe the key visual features of X.
45
-
46
  ### 2. Text Editing Tasks
47
  - All text content must be enclosed in English double quotes `" "`. Keep the original language of the text, and keep the capitalization.
48
  - Both adding new text and replacing existing text are text replacement tasks, For example:
@@ -51,14 +82,12 @@ Please strictly follow the rewriting rules below:
51
  - Replace the visual object to "yy"
52
  - Specify text position, color, and layout only if user has required.
53
  - If font is specified, keep the original language of the font.
54
-
55
  ### 3. Human Editing Tasks
56
  - Make the smallest changes to the given user's prompt.
57
  - If changes to background, action, expression, camera shot, or ambient lighting are required, please list each modification individually.
58
  - **Edits to makeup or facial features / expression must be subtle, not exaggerated, and must preserve the subject's identity consistency.**
59
  > Original: "Add eyebrows to the face"
60
  > Rewritten: "Slightly thicken the person's eyebrows with little change, look natural."
61
-
62
  ### 4. Style Conversion or Enhancement Tasks
63
  - If a style is specified, describe it concisely using key visual features. For example:
64
  > Original: "Disco style"
@@ -69,12 +98,10 @@ Please strictly follow the rewriting rules below:
69
  - Clearly specify the object to be modified. For example:
70
  > Original: Modify the subject in Picture 1 to match the style of Picture 2.
71
  > 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.
72
-
73
  ### 5. Material Replacement
74
  - Clearly specify the object and the material. For example: "Change the material of the apple to papercut style."
75
  - For text material replacement, use the fixed template:
76
  "Change the material of text "xxxx" to laser style"
77
-
78
  ### 6. Logo/Pattern Editing
79
  - Material replacement should preserve the original shape and structure as much as possible. For example:
80
  > Original: "Convert to sapphire material"
@@ -82,23 +109,87 @@ Please strictly follow the rewriting rules below:
82
  - When migrating logos/patterns to new scenes, ensure shape and structure consistency. For example:
83
  > Original: "Migrate the logo in the image to a new scene"
84
  > Rewritten: "Migrate the logo in the image to a new scene, preserving similar shape and structure"
85
-
86
  ### 7. Multi-Image Tasks
87
  - Rewritten prompts must clearly point out which image's element is being modified. For example:
88
  > Original: "Replace the subject of picture 1 with the subject of picture 2"
89
  > Rewritten: "Replace the girl of picture 1 with the boy of picture 2, keeping picture 2's background unchanged"
90
  - For stylization tasks, describe the reference image's style in the rewritten prompt, while preserving the visual content of the source image.
91
-
92
  ## 3. Rationale and Logic Check
93
  - Resolve contradictory instructions: e.g., "Remove all trees but keep all trees" requires logical correction.
94
  - Supplement missing critical information: e.g., if position is unspecified, choose a reasonable area based on composition (near subject, blank space, center/edge, etc.).
95
-
96
  # Output Format Example
97
  ```json
98
  {
99
  "Rewritten": "..."
100
  }
101
  '''
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
  # --- Prompt Enhancement using Hugging Face InferenceClient ---
103
  def polish_prompt_hf(prompt, img_list):
104
  """
@@ -200,19 +291,18 @@ optimize_pipeline_(pipe, image=[Image.new("RGB", (1024, 1024)), Image.new("RGB",
200
  # --- UI Constants and Helpers ---
201
  MAX_SEED = np.iinfo(np.int32).max
202
 
203
- def use_output_as_input(output_images):
204
- """Convert output images to input format for the gallery"""
205
- if output_images is None or len(output_images) == 0:
206
- return []
207
- return output_images
208
 
209
- # --- Main Inference Function (with hardcoded negative prompt) ---
210
- @spaces.GPU(duration=300)
211
  def infer(
212
  images,
213
  prompt,
214
- seed=42,
215
- randomize_seed=False,
216
  true_guidance_scale=1.0,
217
  num_inference_steps=4,
218
  height=None,
@@ -273,6 +363,21 @@ def infer(
273
  # Return images, seed, and make button visible
274
  return image, seed, gr.update(visible=True)
275
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
276
  # --- Examples and UI Layout ---
277
  examples = []
278
 
@@ -288,6 +393,9 @@ css = """
288
  width: 400px;
289
  }
290
  #edit_text{margin-top: -62px !important}
 
 
 
291
  """
292
 
293
  with gr.Blocks(css=css) as demo:
@@ -295,13 +403,16 @@ with gr.Blocks(css=css) as demo:
295
  gr.HTML("""
296
  <div id="logo-title">
297
  <img src="https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-Image/qwen_image_edit_logo.png" alt="Qwen-Image Edit Logo" width="400" style="display: block; margin: 0 auto;">
298
- <h2 style="font-style: italic;color: #5b47d1;margin-top: -27px !important;margin-left: 96px">[Plus] Fast, 4-steps with Qwen Rapid AIO</h2>
299
  </div>
300
  """)
301
  gr.Markdown("""
 
 
302
  [Learn more](https://github.com/QwenLM/Qwen-Image) about the Qwen-Image series.
303
- This demo uses the new [Qwen-Image-Edit-2509](https://huggingface.co/Qwen/Qwen-Image-Edit-2509) with [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 inference.
304
- 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.
 
305
  """)
306
  with gr.Row():
307
  with gr.Column():
@@ -309,6 +420,15 @@ with gr.Blocks(css=css) as demo:
309
  show_label=False,
310
  type="pil",
311
  interactive=True)
 
 
 
 
 
 
 
 
 
312
 
313
  with gr.Column():
314
  result = gr.Gallery(label="Result", show_label=False, type="pil")
@@ -319,7 +439,7 @@ with gr.Blocks(css=css) as demo:
319
  prompt = gr.Text(
320
  label="Prompt",
321
  show_label=False,
322
- placeholder="describe the edit instruction",
323
  container=False,
324
  )
325
  run_button = gr.Button("Edit!", variant="primary")
@@ -372,10 +492,31 @@ with gr.Blocks(css=css) as demo:
372
  )
373
 
374
 
375
- rewrite_prompt = gr.Checkbox(label="Rewrite prompt", value=False)
 
 
 
 
 
 
 
 
 
 
376
 
377
  # gr.Examples(examples=examples, inputs=[prompt], outputs=[result, seed], fn=infer, cache_examples=False)
378
 
 
 
 
 
 
 
 
 
 
 
 
379
  gr.on(
380
  triggers=[run_button.click, prompt.submit],
381
  fn=infer,
 
20
  import base64
21
  import json
22
 
23
+ # System prompt for VLM to suggest next scene prompts
24
+ NEXT_SCENE_SUGGESTION_PROMPT = '''
25
+ # Next Scene Prompt Generator
26
+ You are a cinematic visual continuity expert. Your task is to analyze the provided image and generate a professional "Next Scene" prompt that maintains narrative coherence while introducing organic transitions.
27
+
28
+ ## Analysis Framework:
29
+ 1. Identify the current scene's key elements:
30
+ - Subject(s) and their positions
31
+ - Camera angle and framing (close-up, medium, wide, etc.)
32
+ - Environment and setting
33
+ - Lighting and atmosphere
34
+ - Mood and emotional tone
35
+
36
+ 2. Generate a "Next Scene" prompt following these principles:
37
+ - Begin with specific camera direction (dolly, push, pull, track, pan, tilt, etc.)
38
+ - Describe the transition type:
39
+ * Camera movement: Dolly shots, push-ins, pull-backs, tracking moves
40
+ * Framing evolution: Wide to close-up transitions, angle shifts, reframing
41
+ * Environmental reveals: New characters entering frame, expanded scenery, spatial progression
42
+ * Atmospheric shifts: Lighting changes, weather evolution, time-of-day transitions
43
+ - Maintain compositional coherence with the original scene
44
+ - Include specific visual details about what changes and what remains
45
+
46
+ ## Output Format:
47
+ Generate a single, concise prompt starting with "Next Scene:" followed by the camera movement and visual description.
48
+
49
+ ## Examples of Good Prompts:
50
+ - "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."
51
+ - "Next Scene: The camera tracks forward and tilts down, bringing the sun and helicopters closer into frame as a strong lens flare intensifies."
52
+ - "Next Scene: The camera pans right, removing the dragon and rider from view while revealing more of the floating mountain range in the distance."
53
+ - "Next Scene: The camera dollies in slowly while the morning fog begins to lift, revealing hidden architectural details in the background as golden sunlight breaks through."
54
+ - "Next Scene: A smooth tracking shot follows the subject as they move left, with the background shifting to reveal a previously unseen cityscape bathed in twilight."
55
+
56
+ Return only the prompt text, no additional explanation.
57
+ '''
58
+
59
  SYSTEM_PROMPT = '''
60
  # Edit Instruction Rewriter
61
  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.
 
62
  Please strictly follow the rewriting rules below:
 
63
  ## 1. General Principles
64
  - Keep the rewritten prompt **concise and comprehensive**. Avoid overly long sentences and unnecessary descriptive language.
65
  - If the instruction is contradictory, vague, or unachievable, prioritize reasonable inference and correction, and supplement details when necessary.
66
  - Keep the main part of the original instruction unchanged, only enhancing its clarity, rationality, and visual feasibility.
67
  - All added objects or modifications must align with the logic and style of the scene in the input images.
68
  - If multiple sub-images are to be generated, describe the content of each sub-image individually.
 
69
  ## 2. Task-Type Handling Rules
 
70
  ### 1. Add, Delete, Replace Tasks
71
  - If the instruction is clear (already includes task type, target entity, position, quantity, attributes), preserve the original intent and only refine the grammar.
72
  - If the description is vague, supplement with minimal but sufficient details (category, color, size, orientation, position, etc.). For example:
 
74
  > Rewritten: "Add a light-gray cat in the bottom-right corner, sitting and facing the camera"
75
  - Remove meaningless instructions: e.g., "Add 0 objects" should be ignored or flagged as invalid.
76
  - For replacement tasks, specify "Replace Y with X" and briefly describe the key visual features of X.
 
77
  ### 2. Text Editing Tasks
78
  - All text content must be enclosed in English double quotes `" "`. Keep the original language of the text, and keep the capitalization.
79
  - Both adding new text and replacing existing text are text replacement tasks, For example:
 
82
  - Replace the visual object to "yy"
83
  - Specify text position, color, and layout only if user has required.
84
  - If font is specified, keep the original language of the font.
 
85
  ### 3. Human Editing Tasks
86
  - Make the smallest changes to the given user's prompt.
87
  - If changes to background, action, expression, camera shot, or ambient lighting are required, please list each modification individually.
88
  - **Edits to makeup or facial features / expression must be subtle, not exaggerated, and must preserve the subject's identity consistency.**
89
  > Original: "Add eyebrows to the face"
90
  > Rewritten: "Slightly thicken the person's eyebrows with little change, look natural."
 
91
  ### 4. Style Conversion or Enhancement Tasks
92
  - If a style is specified, describe it concisely using key visual features. For example:
93
  > Original: "Disco style"
 
98
  - Clearly specify the object to be modified. For example:
99
  > Original: Modify the subject in Picture 1 to match the style of Picture 2.
100
  > 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.
 
101
  ### 5. Material Replacement
102
  - Clearly specify the object and the material. For example: "Change the material of the apple to papercut style."
103
  - For text material replacement, use the fixed template:
104
  "Change the material of text "xxxx" to laser style"
 
105
  ### 6. Logo/Pattern Editing
106
  - Material replacement should preserve the original shape and structure as much as possible. For example:
107
  > Original: "Convert to sapphire material"
 
109
  - When migrating logos/patterns to new scenes, ensure shape and structure consistency. For example:
110
  > Original: "Migrate the logo in the image to a new scene"
111
  > Rewritten: "Migrate the logo in the image to a new scene, preserving similar shape and structure"
 
112
  ### 7. Multi-Image Tasks
113
  - Rewritten prompts must clearly point out which image's element is being modified. For example:
114
  > Original: "Replace the subject of picture 1 with the subject of picture 2"
115
  > Rewritten: "Replace the girl of picture 1 with the boy of picture 2, keeping picture 2's background unchanged"
116
  - For stylization tasks, describe the reference image's style in the rewritten prompt, while preserving the visual content of the source image.
 
117
  ## 3. Rationale and Logic Check
118
  - Resolve contradictory instructions: e.g., "Remove all trees but keep all trees" requires logical correction.
119
  - Supplement missing critical information: e.g., if position is unspecified, choose a reasonable area based on composition (near subject, blank space, center/edge, etc.).
 
120
  # Output Format Example
121
  ```json
122
  {
123
  "Rewritten": "..."
124
  }
125
  '''
126
+
127
+ # --- Function to suggest next scene prompts using VLM ---
128
+ def suggest_next_scene_prompt(images):
129
+ """
130
+ Generates a cinematic next scene prompt suggestion using the VLM.
131
+ """
132
+ if not images or len(images) == 0:
133
+ return ""
134
+
135
+ # Ensure HF_TOKEN is set
136
+ api_key = os.environ.get("HF_TOKEN")
137
+ if not api_key:
138
+ print("Warning: HF_TOKEN not set. Cannot generate prompt suggestion.")
139
+ return ""
140
+
141
+ try:
142
+ # Get the first image (or last if using output)
143
+ if isinstance(images[0], tuple):
144
+ img = images[0][0]
145
+ else:
146
+ img = images[0]
147
+
148
+ if isinstance(img, str):
149
+ img = Image.open(img).convert("RGB")
150
+ elif not isinstance(img, Image.Image):
151
+ return ""
152
+
153
+ # Initialize the client
154
+ client = InferenceClient(
155
+ provider="cerebras",
156
+ api_key=api_key,
157
+ )
158
+
159
+ # Format the messages for the chat completions API
160
+ sys_prompt = "You are a cinematic visual continuity expert. Generate next scene prompts that follow professional cinematography principles."
161
+ messages = [
162
+ {"role": "system", "content": sys_prompt},
163
+ {"role": "user", "content": [
164
+ {"image": f"data:image/png;base64,{encode_image(img)}"},
165
+ {"text": NEXT_SCENE_SUGGESTION_PROMPT}
166
+ ]}
167
+ ]
168
+
169
+ # Call the API
170
+ completion = client.chat.completions.create(
171
+ model="Qwen/Qwen3-235B-A22B-Instruct-2507",
172
+ messages=messages,
173
+ temperature=0.7, # Add some creativity
174
+ max_tokens=150
175
+ )
176
+
177
+ # Parse the response
178
+ suggestion = completion.choices[0].message.content
179
+
180
+ # Clean up the suggestion
181
+ suggestion = suggestion.strip()
182
+
183
+ # Ensure it starts with "Next Scene:" if not already
184
+ if not suggestion.startswith("Next Scene:"):
185
+ suggestion = f"Next Scene: {suggestion}"
186
+
187
+ return suggestion
188
+
189
+ except Exception as e:
190
+ print(f"Error generating prompt suggestion: {e}")
191
+ return ""
192
+
193
  # --- Prompt Enhancement using Hugging Face InferenceClient ---
194
  def polish_prompt_hf(prompt, img_list):
195
  """
 
291
  # --- UI Constants and Helpers ---
292
  MAX_SEED = np.iinfo(np.int32).max
293
 
294
+ def use_output_as_input(gallery):
295
+ """Copy the output image to input for iterative editing"""
296
+ if gallery and len(gallery) > 0:
297
+ return gallery
298
+ return None
299
 
300
+ @spaces.GPU(duration=12)
 
301
  def infer(
302
  images,
303
  prompt,
304
+ seed,
305
+ randomize_seed,
306
  true_guidance_scale=1.0,
307
  num_inference_steps=4,
308
  height=None,
 
363
  # Return images, seed, and make button visible
364
  return image, seed, gr.update(visible=True)
365
 
366
+ # --- Function to handle prompt suggestion button ---
367
+ def on_suggest_prompt(images, current_prompt):
368
+ """
369
+ Generates a next scene prompt suggestion when the button is clicked.
370
+ """
371
+ if not images or len(images) == 0:
372
+ return current_prompt, gr.update(visible=False)
373
+
374
+ suggestion = suggest_next_scene_prompt(images)
375
+
376
+ if suggestion:
377
+ return suggestion, gr.update(visible=True, value="✨ Suggestion generated!")
378
+ else:
379
+ return current_prompt, gr.update(visible=True, value="❌ Could not generate suggestion")
380
+
381
  # --- Examples and UI Layout ---
382
  examples = []
383
 
 
393
  width: 400px;
394
  }
395
  #edit_text{margin-top: -62px !important}
396
+ .suggest-btn {
397
+ background: linear-gradient(90deg, #5b47d1 0%, #7c6fe1 100%);
398
+ }
399
  """
400
 
401
  with gr.Blocks(css=css) as demo:
 
403
  gr.HTML("""
404
  <div id="logo-title">
405
  <img src="https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-Image/qwen_image_edit_logo.png" alt="Qwen-Image Edit Logo" width="400" style="display: block; margin: 0 auto;">
406
+ <h2 style="font-style: italic;color: #5b47d1;margin-top: -27px !important;margin-left: 96px">[Plus] Fast, 4-steps with Qwen Rapid AIO + Next Scene LoRA</h2>
407
  </div>
408
  """)
409
  gr.Markdown("""
410
+ **Enhanced with Next Scene LoRA for cinematic continuity!** 🎬
411
+
412
  [Learn more](https://github.com/QwenLM/Qwen-Image) about the Qwen-Image series.
413
+ This demo uses [Qwen-Image-Edit-2509](https://huggingface.co/Qwen/Qwen-Image-Edit-2509) with [Next Scene LoRA](https://huggingface.co/lovis93/next-scene-qwen-image-lora-2509) for cinematic storytelling.
414
+
415
+ **New Feature:** Click "🎬 Suggest Next Scene" to get AI-generated cinematic prompts that maintain visual continuity!
416
  """)
417
  with gr.Row():
418
  with gr.Column():
 
420
  show_label=False,
421
  type="pil",
422
  interactive=True)
423
+
424
+ # Add the suggest prompt button below input images
425
+ suggest_btn = gr.Button("🎬 Suggest Next Scene Prompt",
426
+ variant="primary",
427
+ elem_classes=["suggest-btn"])
428
+ suggest_status = gr.Textbox(visible=False,
429
+ label="",
430
+ interactive=False,
431
+ max_lines=1)
432
 
433
  with gr.Column():
434
  result = gr.Gallery(label="Result", show_label=False, type="pil")
 
439
  prompt = gr.Text(
440
  label="Prompt",
441
  show_label=False,
442
+ placeholder="describe the edit instruction (or click 'Suggest Next Scene' for AI suggestions)",
443
  container=False,
444
  )
445
  run_button = gr.Button("Edit!", variant="primary")
 
492
  )
493
 
494
 
495
+ rewrite_prompt = gr.Checkbox(label="Enhance prompt (recommended)", value=True)
496
+
497
+ gr.Markdown("""
498
+ ### 🎬 Next Scene Tips:
499
+ - **Camera Movements**: Prompts will include dolly shots, push-ins, pull-backs, tracking moves
500
+ - **Framing Evolution**: Wide to close-up transitions, angle shifts, reframing
501
+ - **Environmental Reveals**: New characters, expanded scenery, spatial progression
502
+ - **Atmospheric Shifts**: Lighting changes, weather evolution, time transitions
503
+
504
+ **Pro tip**: Chain multiple generations to create cinematic storyboards!
505
+ """)
506
 
507
  # gr.Examples(examples=examples, inputs=[prompt], outputs=[result, seed], fn=infer, cache_examples=False)
508
 
509
+ # Event handler for suggest prompt button
510
+ suggest_btn.click(
511
+ fn=on_suggest_prompt,
512
+ inputs=[input_images, prompt],
513
+ outputs=[prompt, suggest_status]
514
+ ).then(
515
+ fn=lambda: gr.update(visible=False),
516
+ outputs=[suggest_status],
517
+ _js="() => setTimeout(() => {}, 3000)" # Hide status after 3 seconds
518
+ )
519
+
520
  gr.on(
521
  triggers=[run_button.click, prompt.submit],
522
  fn=infer,