prithivMLmods commited on
Commit
f5d0ebd
Β·
verified Β·
1 Parent(s): 19d6d1f

update app

Browse files
Files changed (1) hide show
  1. app.py +29 -33
app.py CHANGED
@@ -56,8 +56,8 @@ except Exception as e:
56
  NCII_MODEL_ID = "hfmlsoc/ncii-light-guard-v01"
57
  NCII_UNSAFE_LABEL = "ncii"
58
  NCII_THRESHOLD = 0.5
59
- NCII_BLOCK_MESSAGE = "Your entered prompt is flagged as NCII (non-consensual intimate imagery) and your request will not be processed. Try with safe prompts."
60
-
61
  print("Loading NCII safety guard model...")
62
  try:
63
  ncii_guard = hf_pipeline("text-classification", model=NCII_MODEL_ID, device=-1)
@@ -65,7 +65,7 @@ try:
65
  except Exception as e:
66
  ncii_guard = None
67
  print(f"Warning: Could not load NCII guard model ({NCII_MODEL_ID}): {e}")
68
-
69
  def check_ncii_safety(prompt_text):
70
  if ncii_guard is None or not prompt_text or not prompt_text.strip():
71
  return False, "unknown", 0.0
@@ -81,31 +81,14 @@ def check_ncii_safety(prompt_text):
81
  print(f"NCII guard inference error: {e}")
82
  return False, "unknown", 0.0
83
 
 
84
  EXAMPLES_CONFIG = [
85
- {
86
- "images": ["examples/1.jpg"],
87
- "prompt": "cinematic polaroid with soft grain subtle vignette gentle lighting white frame handwritten photographed 'Fire-Edit' preserving realistic texture and details.",
88
- },
89
- {
90
- "images": ["examples/2.jpg"],
91
- "prompt": "Transform the image into a dotted cartoon style.",
92
- },
93
- {
94
- "images": ["examples/3.jpeg"],
95
- "prompt": "Convert it to black and white.",
96
- },
97
- {
98
- "images": ["examples/4.jpg", "examples/5.jpg"],
99
- "prompt": "Replace her glasses with the new glasses from image 1.",
100
- },
101
- {
102
- "images": ["examples/8.jpg", "examples/9.png"],
103
- "prompt": "Replace the current clothing with the clothing from the reference image 2. Keep the person's face, hairstyle, body pose, background, lighting, and camera angle unchanged. Ensure the new outfit fits naturally with realistic fabric texture, proper shadows, folds, and accurate proportions. Match the lighting, color tone, and overall style for a seamless and high-quality result.",
104
- },
105
- {
106
- "images": ["examples/10.jpg", "examples/11.png"],
107
- "prompt": "Replace the current clothing with the clothing from the reference image 2. Keep the person's face, hairstyle, body pose, background, lighting, and camera angle unchanged. Ensure the new outfit fits naturally with realistic fabric texture, proper shadows, folds, and accurate proportions. Match the lighting, color tone, and overall style for a seamless and high-quality result.",
108
- },
109
  ]
110
 
111
  def make_thumb_b64(path, max_dim=220):
@@ -135,6 +118,7 @@ def encode_full_image(path):
135
  return ""
136
 
137
  def build_client_config():
 
138
  examples = []
139
  for i, ex in enumerate(EXAMPLES_CONFIG):
140
  examples.append({
@@ -204,9 +188,10 @@ def infer(
204
  guidance_scale: float,
205
  steps: int,
206
  ) -> dict:
207
- """Edit one or more images with FireRed-Image-Edit + NCII safety guard.
208
 
209
- Returns {"image": <base64 PNG data URL>, "seed": <seed used>}.
 
210
  """
211
  gc.collect()
212
  torch.cuda.empty_cache()
@@ -217,16 +202,23 @@ def infer(
217
  if not prompt or prompt.strip() == "":
218
  raise gr.Error("Please enter an edit prompt.")
219
 
220
- # NCII safety check
221
  is_unsafe, _, _ = check_ncii_safety(prompt)
222
  if is_unsafe:
223
- raise gr.Error(NCII_BLOCK_MESSAGE)
 
 
 
 
224
 
225
  if randomize_seed:
226
  seed = random.randint(0, MAX_SEED)
227
 
228
  generator = torch.Generator(device=device).manual_seed(seed)
229
- negative_prompt = "worst quality, low quality, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, jpeg artifacts, signature, watermark, username, blurry"
 
 
 
230
  width, height = update_dimensions_on_upload(pil_images[0])
231
 
232
  try:
@@ -240,13 +232,14 @@ def infer(
240
  generator=generator,
241
  true_cfg_scale=guidance_scale,
242
  ).images[0]
243
- return {"image": pil_to_b64_png(result_image), "seed": seed}
244
  except Exception as e:
245
  raise e
246
  finally:
247
  gc.collect()
248
  torch.cuda.empty_cache()
249
 
 
250
  @app.api(name="load_example", queue=False)
251
  def load_example(idx: float) -> dict:
252
  """Return base64-encoded example images + prompt for a given example index."""
@@ -265,16 +258,19 @@ def load_example(idx: float) -> dict:
265
  names.append(os.path.basename(path))
266
  return {"images": b64_list, "prompt": ex["prompt"], "names": names, "status": "ok"}
267
 
 
268
  @app.get("/api/config")
269
  def client_config():
270
  """Plain FastAPI route: example card data for the frontend."""
271
  return CLIENT_CONFIG
272
 
 
273
  @app.get("/", response_class=HTMLResponse)
274
  async def homepage():
275
  html_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "index.html")
276
  with open(html_path, "r", encoding="utf-8") as f:
277
  return f.read()
278
 
 
279
  if __name__ == "__main__":
280
  app.launch(show_error=True, mcp_server=True)
 
56
  NCII_MODEL_ID = "hfmlsoc/ncii-light-guard-v01"
57
  NCII_UNSAFE_LABEL = "ncii"
58
  NCII_THRESHOLD = 0.5
59
+ NCII_BLOCK_MESSAGE = "You entered prompt is NCII (non-consensual intimate imagery) and your request will not be processed. Try with Safe Prompts."
60
+
61
  print("Loading NCII safety guard model...")
62
  try:
63
  ncii_guard = hf_pipeline("text-classification", model=NCII_MODEL_ID, device=-1)
 
65
  except Exception as e:
66
  ncii_guard = None
67
  print(f"Warning: Could not load NCII guard model ({NCII_MODEL_ID}): {e}")
68
+
69
  def check_ncii_safety(prompt_text):
70
  if ncii_guard is None or not prompt_text or not prompt_text.strip():
71
  return False, "unknown", 0.0
 
81
  print(f"NCII guard inference error: {e}")
82
  return False, "unknown", 0.0
83
 
84
+ # ── Examples Config ───────────────────────────────────────────────────────────
85
  EXAMPLES_CONFIG = [
86
+ {"images": ["examples/1.jpg"], "prompt": "cinematic polaroid with soft grain subtle vignette gentle lighting white frame handwritten photographed 'Fire-Edit' preserving realistic texture and details."},
87
+ {"images": ["examples/2.jpg"], "prompt": "Transform the image into a dotted cartoon style."},
88
+ {"images": ["examples/3.jpeg"], "prompt": "Convert it to black and white."},
89
+ {"images": ["examples/4.jpg", "examples/5.jpg"], "prompt": "Replace her glasses with the new glasses from image 1."},
90
+ {"images": ["examples/8.jpg", "examples/9.png"], "prompt": "Replace the current clothing with the clothing from the reference image 2. Keep the person's face, hairstyle, body pose, background, lighting, and camera angle unchanged. Ensure the new outfit fits naturally with realistic fabric texture, proper shadows, folds, and accurate proportions. Match the lighting, color tone, and overall style for a seamless and high-quality result."},
91
+ {"images": ["examples/10.jpg", "examples/11.png"], "prompt": "Replace the current clothing with the clothing from the reference image 2. Keep the person's face, hairstyle, body pose, background, lighting, and camera angle unchanged. Ensure the new outfit fits naturally with realistic fabric texture, proper shadows, folds, and accurate proportions. Match the lighting, color tone, and overall style for a seamless and high-quality result."},
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  ]
93
 
94
  def make_thumb_b64(path, max_dim=220):
 
118
  return ""
119
 
120
  def build_client_config():
121
+ """Static config consumed by the frontend: example cards."""
122
  examples = []
123
  for i, ex in enumerate(EXAMPLES_CONFIG):
124
  examples.append({
 
188
  guidance_scale: float,
189
  steps: int,
190
  ) -> dict:
191
+ """Edit one or more images with FireRed-Image-Edit-1.1.
192
 
193
+ Returns {"image": <base64 PNG data URL>, "seed": <seed used>, "status": "success"}
194
+ or {"status": "blocked", "message": <warning>} if NCII triggers.
195
  """
196
  gc.collect()
197
  torch.cuda.empty_cache()
 
202
  if not prompt or prompt.strip() == "":
203
  raise gr.Error("Please enter an edit prompt.")
204
 
205
+ # ── NCII safety check ──
206
  is_unsafe, _, _ = check_ncii_safety(prompt)
207
  if is_unsafe:
208
+ gc.collect()
209
+ torch.cuda.empty_cache()
210
+ # Returning a blocked status instead of raising an error
211
+ # so the frontend can gracefully catch it and display a warning toast.
212
+ return {"image": "", "seed": seed, "status": "blocked", "message": NCII_BLOCK_MESSAGE}
213
 
214
  if randomize_seed:
215
  seed = random.randint(0, MAX_SEED)
216
 
217
  generator = torch.Generator(device=device).manual_seed(seed)
218
+ negative_prompt = (
219
+ "worst quality, low quality, bad anatomy, bad hands, text, error, missing fingers, "
220
+ "extra digit, fewer digits, cropped, jpeg artifacts, signature, watermark, username, blurry"
221
+ )
222
  width, height = update_dimensions_on_upload(pil_images[0])
223
 
224
  try:
 
232
  generator=generator,
233
  true_cfg_scale=guidance_scale,
234
  ).images[0]
235
+ return {"image": pil_to_b64_png(result_image), "seed": seed, "status": "success"}
236
  except Exception as e:
237
  raise e
238
  finally:
239
  gc.collect()
240
  torch.cuda.empty_cache()
241
 
242
+
243
  @app.api(name="load_example", queue=False)
244
  def load_example(idx: float) -> dict:
245
  """Return base64-encoded example images + prompt for a given example index."""
 
258
  names.append(os.path.basename(path))
259
  return {"images": b64_list, "prompt": ex["prompt"], "names": names, "status": "ok"}
260
 
261
+
262
  @app.get("/api/config")
263
  def client_config():
264
  """Plain FastAPI route: example card data for the frontend."""
265
  return CLIENT_CONFIG
266
 
267
+
268
  @app.get("/", response_class=HTMLResponse)
269
  async def homepage():
270
  html_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "index.html")
271
  with open(html_path, "r", encoding="utf-8") as f:
272
  return f.read()
273
 
274
+
275
  if __name__ == "__main__":
276
  app.launch(show_error=True, mcp_server=True)