Nad54 commited on
Commit
a32b4dd
·
verified ·
1 Parent(s): 76455e5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +17 -16
app.py CHANGED
@@ -22,8 +22,8 @@ from pipeline import InstantCharacterFluxPipeline
22
  MAX_SEED = np.iinfo(np.int32).max
23
  device = "cuda" if torch.cuda.is_available() else "cpu"
24
  dtype = torch.float16 # L4: FP16 OK
25
- HF_TOKEN = os.environ.get("HF_TOKEN") or os.environ.get("HUGGINGFACEHUB_API_TOKEN")
26
 
 
27
  def need_token_guard():
28
  if HF_TOKEN is None:
29
  raise gr.Error(
@@ -36,32 +36,32 @@ def need_token_guard():
36
  # =========================
37
  base_model = "black-forest-labs/FLUX.1-dev"
38
  image_encoder_path = "google/siglip-so400m-patch14-384"
39
- image_encoder_2_path = "facebook/dinov2-giant"
 
40
  birefnet_path = "ZhengPeng7/BiRefNet"
41
 
42
  # Ton LoRA One Piece (local)
43
- onepiece_flux_lora_path = "./onepiece_flux_v2.safetensors" # assure-toi qu'il est bien à la racine
44
  onepiece_flux_trigger = "onepiece style"
45
 
46
  def _dl(repo_id, filename, token=None):
47
  return hf_hub_download(repo_id=repo_id, filename=filename, token=token)
48
 
49
  need_token_guard()
50
- # Uniquement l'IP-Adapter (nécessaire à l'identité)
51
  ip_adapter_path = _dl("tencent/InstantCharacter", "instantcharacter_ip-adapter.bin", HF_TOKEN)
52
 
53
  # =========================
54
- # PIPELINE (GPU only, low RAM)
55
  # =========================
56
  pipe = InstantCharacterFluxPipeline.from_pretrained(
57
  base_model,
58
  torch_dtype=dtype,
59
  token=HF_TOKEN,
60
- low_cpu_mem_usage=True, # réduit le pic RAM au chargement
61
  )
62
  pipe.to(device)
63
 
64
- # xFormers si dispo (baisse l'empreinte GPU)
65
  try:
66
  pipe.enable_xformers_memory_efficient_attention()
67
  except Exception:
@@ -72,11 +72,16 @@ if hasattr(pipe, "vae"):
72
  if hasattr(pipe.vae, "enable_slicing"): pipe.vae.enable_slicing()
73
  if hasattr(pipe.vae, "enable_tiling"): pipe.vae.enable_tiling()
74
 
75
- pipe.init_adapter(
 
76
  image_encoder_path=image_encoder_path,
77
- image_encoder_2_path=image_encoder_2_path,
78
- subject_ipadapter_cfg=dict(subject_ip_adapter_path=ip_adapter_path, nb_token=1024),
79
  )
 
 
 
 
 
80
 
81
  # =========================
82
  # BiRefNet : lazy-load sur CPU
@@ -156,12 +161,10 @@ def create_image(
156
  ):
157
  if input_image is None:
158
  raise gr.Error("Merci d'uploader une image de visage.")
159
-
160
  if use_onepiece_lora and not os.path.exists(onepiece_flux_lora_path):
161
  raise gr.Error(f"Fichier LoRA manquant : {onepiece_flux_lora_path}")
162
 
163
  input_image = remove_bkg(input_image)
164
-
165
  generator = torch.Generator(device=device).manual_seed(int(seed))
166
 
167
  if use_onepiece_lora:
@@ -195,9 +198,9 @@ def create_image(
195
  # =========================
196
  # UI
197
  # =========================
198
- title = "<h1 align='center'>InstantCharacter (FLUX.1-dev) + One Piece (FLUX LoRA) — minimal</h1>"
199
  description = (
200
- "GPU-only (FP16) pour éviter la limite RAM 30 Go. "
201
  "Départ en 768×768, tu peux monter à 896→1024 si stable."
202
  )
203
 
@@ -208,12 +211,10 @@ with block:
208
  with gr.Row():
209
  with gr.Column():
210
  image_pil = gr.Image(label="Source Image", type="pil")
211
-
212
  prompt = gr.Textbox(
213
  label="Prompt",
214
  value="onepiece style, a pirate character standing on a ship deck, shonen manga, strong black line art, cel shading, expressive eyes, dynamic pose, clean linework"
215
  )
216
-
217
  scale = gr.Slider(0.0, 1.5, 1.0, 0.01, label="Scale (face strength)")
218
  use_onepiece_lora = gr.Checkbox(value=True, label="Use One Piece (FLUX LoRA)")
219
  lora_strength = gr.Slider(0.0, 1.5, 0.85, 0.05, label="LoRA strength")
 
22
  MAX_SEED = np.iinfo(np.int32).max
23
  device = "cuda" if torch.cuda.is_available() else "cpu"
24
  dtype = torch.float16 # L4: FP16 OK
 
25
 
26
+ HF_TOKEN = os.environ.get("HF_TOKEN") or os.environ.get("HUGGINGFACEHUB_API_TOKEN")
27
  def need_token_guard():
28
  if HF_TOKEN is None:
29
  raise gr.Error(
 
36
  # =========================
37
  base_model = "black-forest-labs/FLUX.1-dev"
38
  image_encoder_path = "google/siglip-so400m-patch14-384"
39
+ # 🔻 On supprime l'encodeur 2 (DINOv2-giant) pour sauver ~10 Go RAM
40
+ image_encoder_2_path = None
41
  birefnet_path = "ZhengPeng7/BiRefNet"
42
 
43
  # Ton LoRA One Piece (local)
44
+ onepiece_flux_lora_path = "./onepiece_flux_v2.safetensors"
45
  onepiece_flux_trigger = "onepiece style"
46
 
47
  def _dl(repo_id, filename, token=None):
48
  return hf_hub_download(repo_id=repo_id, filename=filename, token=token)
49
 
50
  need_token_guard()
51
+ # Uniquement l'IP-Adapter (nécessaire à l'identité) — 5.6 Go
52
  ip_adapter_path = _dl("tencent/InstantCharacter", "instantcharacter_ip-adapter.bin", HF_TOKEN)
53
 
54
  # =========================
55
+ # PIPELINE (GPU only, low RAM peak)
56
  # =========================
57
  pipe = InstantCharacterFluxPipeline.from_pretrained(
58
  base_model,
59
  torch_dtype=dtype,
60
  token=HF_TOKEN,
61
+ low_cpu_mem_usage=True, # pic RAM à l'init
62
  )
63
  pipe.to(device)
64
 
 
65
  try:
66
  pipe.enable_xformers_memory_efficient_attention()
67
  except Exception:
 
72
  if hasattr(pipe.vae, "enable_slicing"): pipe.vae.enable_slicing()
73
  if hasattr(pipe.vae, "enable_tiling"): pipe.vae.enable_tiling()
74
 
75
+ # 🔻 Init de l'adapter: 1 seul image encoder (SigLIP) + moins de tokens
76
+ adapter_kwargs = dict(
77
  image_encoder_path=image_encoder_path,
78
+ subject_ipadapter_cfg=dict(subject_ip_adapter_path=ip_adapter_path, nb_token=512), # 1024 -> 512 pour baisser mémoire
 
79
  )
80
+ # N'ajoute image_encoder_2_path que s'il existe
81
+ if image_encoder_2_path:
82
+ adapter_kwargs["image_encoder_2_path"] = image_encoder_2_path
83
+
84
+ pipe.init_adapter(**adapter_kwargs)
85
 
86
  # =========================
87
  # BiRefNet : lazy-load sur CPU
 
161
  ):
162
  if input_image is None:
163
  raise gr.Error("Merci d'uploader une image de visage.")
 
164
  if use_onepiece_lora and not os.path.exists(onepiece_flux_lora_path):
165
  raise gr.Error(f"Fichier LoRA manquant : {onepiece_flux_lora_path}")
166
 
167
  input_image = remove_bkg(input_image)
 
168
  generator = torch.Generator(device=device).manual_seed(int(seed))
169
 
170
  if use_onepiece_lora:
 
198
  # =========================
199
  # UI
200
  # =========================
201
+ title = "<h1 align='center'>InstantCharacter (FLUX.1-dev) + One Piece (FLUX LoRA) — single encoder</h1>"
202
  description = (
203
+ "GPU-only (FP16), low_cpu_mem_usage=True, **sans DINOv2-giant** pour éviter la limite RAM 30 Go. "
204
  "Départ en 768×768, tu peux monter à 896→1024 si stable."
205
  )
206
 
 
211
  with gr.Row():
212
  with gr.Column():
213
  image_pil = gr.Image(label="Source Image", type="pil")
 
214
  prompt = gr.Textbox(
215
  label="Prompt",
216
  value="onepiece style, a pirate character standing on a ship deck, shonen manga, strong black line art, cel shading, expressive eyes, dynamic pose, clean linework"
217
  )
 
218
  scale = gr.Slider(0.0, 1.5, 1.0, 0.01, label="Scale (face strength)")
219
  use_onepiece_lora = gr.Checkbox(value=True, label="Use One Piece (FLUX LoRA)")
220
  lora_strength = gr.Slider(0.0, 1.5, 0.85, 0.05, label="LoRA strength")