cereeenn120 commited on
Commit
b0b7a1b
·
1 Parent(s): 8a4d7c3

Create initial requirements.txt

Browse files
Files changed (2) hide show
  1. app.py +51 -51
  2. requirements.txt +10 -0
app.py CHANGED
@@ -3,13 +3,13 @@ FLUX.2 [klein] 9B — Character Consistency Space
3
  ================================================
4
  • Tab 1 │ Karakter Referansı : Prompt + max 4 referans görsel → yeni görsel
5
  • Tab 2 │ img2img + Referans : Giriş görseli + prompt + max 3 referans → düzenlenmiş görsel
6
-
7
  NOTLAR:
8
  - Bu model, multi-reference desteğini NATIVE olarak sunar; ayrı IP-Adapter gerekmez.
9
  - FLUX Non-Commercial License geçerlidir. Space'inize HF_TOKEN secret'ı eklemeyi unutmayın.
10
  - Gereksinim: ~29 GB VRAM (A100 / H100 önerilir).
11
  """
12
-
13
  import os
14
  import random
15
  import gradio as gr
@@ -17,23 +17,23 @@ import numpy as np
17
  import torch
18
  from diffusers import Flux2KleinPipeline
19
  from PIL import Image
20
-
21
  # ──────────────────────────────────────────────
22
  # Sabitler
23
  # ──────────────────────────────────────────────
24
-
25
  MODEL_ID = "black-forest-labs/FLUX.2-klein-9B"
26
  DTYPE = torch.bfloat16
27
  MAX_REFS_T2I = 4 # karakter referansı tabı için maks referans görseli
28
  MAX_REFS_I2I = 3 # img2img tabı için maks referans görseli
29
-
30
  # ──────────────────────────────────────────────
31
  # Model yükleme (lazy, singleton)
32
  # ──────────────────────────────────────────────
33
-
34
  _pipe: Flux2KleinPipeline | None = None
35
-
36
-
37
  def get_pipe() -> Flux2KleinPipeline:
38
  global _pipe
39
  if _pipe is None:
@@ -44,15 +44,15 @@ def get_pipe() -> Flux2KleinPipeline:
44
  torch_dtype=DTYPE,
45
  token=token,
46
  )
47
- _pipe.enable_model_cpu_offload() # VRAM'ı verimli kullan
48
  print("[INFO] Model hazır.")
49
  return _pipe
50
-
51
-
52
  # ──────────────────────────────────────────────
53
  # Yardımcı fonksiyonlar
54
  # ──────────────────────────────────────────────
55
-
56
  def to_pil(img) -> Image.Image | None:
57
  """Gradio'dan gelen numpy array veya PIL görselini PIL'e çevirir."""
58
  if img is None:
@@ -62,26 +62,26 @@ def to_pil(img) -> Image.Image | None:
62
  if isinstance(img, Image.Image):
63
  return img.convert("RGB")
64
  return None
65
-
66
-
67
  def collect_refs(*images) -> list[Image.Image] | None:
68
  """None olmayan görselleri filtreler, PIL listesi döndürür."""
69
  refs = [to_pil(img) for img in images if img is not None]
70
  return refs if refs else None
71
-
72
-
73
  def make_generator(seed: int) -> torch.Generator | None:
74
  if seed == -1:
75
  seed = random.randint(0, 2**32 - 1)
76
  gen = torch.Generator()
77
  gen.manual_seed(seed)
78
  return gen
79
-
80
-
81
  # ──────────────────────────────────────────────
82
  # Tab 1 — Karakter Referansı (Multi-Ref T2I)
83
  # ──────────────────────────────────────────────
84
-
85
  def run_t2i(
86
  prompt: str,
87
  ref1, ref2, ref3, ref4,
@@ -93,11 +93,11 @@ def run_t2i(
93
  ) -> Image.Image:
94
  if not prompt.strip():
95
  raise gr.Error("Lütfen bir prompt girin.")
96
-
97
  refs = collect_refs(ref1, ref2, ref3, ref4)
98
  gen = make_generator(seed)
99
  pipe = get_pipe()
100
-
101
  result = pipe(
102
  prompt=prompt,
103
  image=refs, # None → saf t2i | list → multi-ref yönlendirmeli üretim
@@ -107,14 +107,14 @@ def run_t2i(
107
  guidance_scale=guidance,
108
  generator=gen,
109
  ).images[0]
110
-
111
  return result
112
-
113
-
114
  # ──────────────────────────────────────────────
115
  # Tab 2 — img2img + Karakter Referansı
116
  # ──────────────────────────────────────────────
117
-
118
  def run_i2i(
119
  prompt: str,
120
  input_img,
@@ -130,18 +130,18 @@ def run_i2i(
130
  raise gr.Error("Lütfen bir prompt girin.")
131
  if input_img is None:
132
  raise gr.Error("Lütfen düzenlemek istediğiniz bir giriş görseli yükleyin.")
133
-
134
  base = to_pil(input_img)
135
  refs = collect_refs(ref1, ref2, ref3)
136
-
137
  # Tüm görseller tek liste olarak verilir:
138
  # [giriş görseli] + [karakter referansları]
139
  # Model, prompt'a göre hangi unsurları transfer edeceğine karar verir.
140
  all_images = ([base] + refs) if refs else [base]
141
-
142
  gen = make_generator(seed)
143
  pipe = get_pipe()
144
-
145
  # strength parametresi img2img gürültü oranını kontrol eder.
146
  # Flux2KleinPipeline bu parametreyi desteklemiyorsa sessizce atlanır.
147
  call_kwargs = dict(
@@ -158,30 +158,30 @@ def run_i2i(
158
  except TypeError:
159
  # strength desteklenmiyorsa (pipeline versiyonuna göre değişebilir)
160
  result = pipe(**call_kwargs).images[0]
161
-
162
  return result
163
-
164
-
165
  # ──────────────────────────────────────────────
166
  # Gradio Arayüzü
167
  # ──────────────────────────────────────────────
168
-
169
  CSS = """
170
  h1 { text-align: center; }
171
  .ref-row { gap: 8px !important; }
172
  footer { display: none !important; }
173
  """
174
-
175
  # Paylaşılan çözünürlük seçenekleri
176
  RESOLUTION_CHOICES = [512, 768, 1024, 1280]
177
-
178
- with gr.Blocks(css=CSS, title="FLUX.2 [klein] Character Studio") as demo:
179
-
180
  gr.Markdown(
181
- "# 🎭 FLUX.2 \[klein\] 9B — Character Consistency Studio\n"
182
  "> Multi-reference karakter tutarlılığı · Native multi-image support · 4-step distilled"
183
  )
184
-
185
  # ── Tab 1: Karakter Referansı ──────────────────────────────────────────
186
  with gr.Tab("🧑‍🎨 Karakter Referansı (T2I)"):
187
  gr.Markdown(
@@ -201,7 +201,7 @@ with gr.Blocks(css=CSS, title="FLUX.2 [klein] Character Studio") as demo:
201
  t2i_ref2 = gr.Image(label="Ref 2", type="pil", height=140)
202
  t2i_ref3 = gr.Image(label="Ref 3", type="pil", height=140)
203
  t2i_ref4 = gr.Image(label="Ref 4", type="pil", height=140)
204
-
205
  with gr.Accordion("⚙️ Gelişmiş Ayarlar", open=False):
206
  with gr.Row():
207
  t2i_width = gr.Dropdown(RESOLUTION_CHOICES, value=1024, label="Genişlik")
@@ -209,12 +209,12 @@ with gr.Blocks(css=CSS, title="FLUX.2 [klein] Character Studio") as demo:
209
  t2i_steps = gr.Slider(1, 8, value=4, step=1, label="Adım Sayısı (Steps)")
210
  t2i_guidance = gr.Slider(0.0, 5.0, value=1.0, step=0.1, label="Guidance Scale")
211
  t2i_seed = gr.Number(value=-1, label="Seed (-1 = rastgele)", precision=0)
212
-
213
  t2i_btn = gr.Button("🎨 Oluştur", variant="primary", size="lg")
214
-
215
  with gr.Column(scale=1):
216
  t2i_out = gr.Image(label="Çıktı", type="pil", height=520)
217
-
218
  t2i_btn.click(
219
  fn=run_t2i,
220
  inputs=[
@@ -225,7 +225,7 @@ with gr.Blocks(css=CSS, title="FLUX.2 [klein] Character Studio") as demo:
225
  ],
226
  outputs=t2i_out,
227
  )
228
-
229
  # ── Tab 2: img2img + Referans ──────────────────────────────────────────
230
  with gr.Tab("🖼️ img2img + Referans"):
231
  gr.Markdown(
@@ -257,12 +257,12 @@ with gr.Blocks(css=CSS, title="FLUX.2 [klein] Character Studio") as demo:
257
  i2i_steps = gr.Slider(1, 8, value=4, step=1, label="Adım Sayısı (Steps)")
258
  i2i_guidance = gr.Slider(0.0, 5.0, value=1.0, step=0.1, label="Guidance Scale")
259
  i2i_seed = gr.Number(value=-1, label="Seed (-1 = rastgele)", precision=0)
260
-
261
  i2i_btn = gr.Button("🖌️ Düzenle", variant="primary", size="lg")
262
-
263
  with gr.Column(scale=1):
264
  i2i_out = gr.Image(label="Çıktı", type="pil", height=520)
265
-
266
  i2i_btn.click(
267
  fn=run_i2i,
268
  inputs=[
@@ -274,7 +274,7 @@ with gr.Blocks(css=CSS, title="FLUX.2 [klein] Character Studio") as demo:
274
  ],
275
  outputs=i2i_out,
276
  )
277
-
278
  # ── Bilgi Notu ──────────────────────────────────────────────────────────
279
  gr.Markdown(
280
  "---\n"
@@ -282,10 +282,10 @@ with gr.Blocks(css=CSS, title="FLUX.2 [klein] Character Studio") as demo:
282
  "**Lisans:** FLUX Non-Commercial · "
283
  "**Gereksinim:** ~29 GB VRAM (A100 / H100)"
284
  )
285
-
286
  # ──────────────────────────────────────────────
287
  # Başlatma
288
  # ──────────────────────────────────────────────
289
-
290
  if __name__ == "__main__":
291
- demo.launch()
 
3
  ================================================
4
  • Tab 1 │ Karakter Referansı : Prompt + max 4 referans görsel → yeni görsel
5
  • Tab 2 │ img2img + Referans : Giriş görseli + prompt + max 3 referans → düzenlenmiş görsel
6
+
7
  NOTLAR:
8
  - Bu model, multi-reference desteğini NATIVE olarak sunar; ayrı IP-Adapter gerekmez.
9
  - FLUX Non-Commercial License geçerlidir. Space'inize HF_TOKEN secret'ı eklemeyi unutmayın.
10
  - Gereksinim: ~29 GB VRAM (A100 / H100 önerilir).
11
  """
12
+ import spaces
13
  import os
14
  import random
15
  import gradio as gr
 
17
  import torch
18
  from diffusers import Flux2KleinPipeline
19
  from PIL import Image
20
+
21
  # ──────────────────────────────────────────────
22
  # Sabitler
23
  # ──────────────────────────────────────────────
24
+
25
  MODEL_ID = "black-forest-labs/FLUX.2-klein-9B"
26
  DTYPE = torch.bfloat16
27
  MAX_REFS_T2I = 4 # karakter referansı tabı için maks referans görseli
28
  MAX_REFS_I2I = 3 # img2img tabı için maks referans görseli
29
+
30
  # ──────────────────────────────────────────────
31
  # Model yükleme (lazy, singleton)
32
  # ──────────────────────────────────────────────
33
+
34
  _pipe: Flux2KleinPipeline | None = None
35
+
36
+
37
  def get_pipe() -> Flux2KleinPipeline:
38
  global _pipe
39
  if _pipe is None:
 
44
  torch_dtype=DTYPE,
45
  token=token,
46
  )
47
+ #_pipe.enable_model_cpu_offload() # VRAM'ı verimli kullan
48
  print("[INFO] Model hazır.")
49
  return _pipe
50
+
51
+
52
  # ──────────────────────────────────────────────
53
  # Yardımcı fonksiyonlar
54
  # ──────────────────────────────────────────────
55
+
56
  def to_pil(img) -> Image.Image | None:
57
  """Gradio'dan gelen numpy array veya PIL görselini PIL'e çevirir."""
58
  if img is None:
 
62
  if isinstance(img, Image.Image):
63
  return img.convert("RGB")
64
  return None
65
+
66
+
67
  def collect_refs(*images) -> list[Image.Image] | None:
68
  """None olmayan görselleri filtreler, PIL listesi döndürür."""
69
  refs = [to_pil(img) for img in images if img is not None]
70
  return refs if refs else None
71
+
72
+
73
  def make_generator(seed: int) -> torch.Generator | None:
74
  if seed == -1:
75
  seed = random.randint(0, 2**32 - 1)
76
  gen = torch.Generator()
77
  gen.manual_seed(seed)
78
  return gen
79
+
80
+
81
  # ──────────────────────────────────────────────
82
  # Tab 1 — Karakter Referansı (Multi-Ref T2I)
83
  # ──────────────────────────────────────────────
84
+ @spaces.GPU
85
  def run_t2i(
86
  prompt: str,
87
  ref1, ref2, ref3, ref4,
 
93
  ) -> Image.Image:
94
  if not prompt.strip():
95
  raise gr.Error("Lütfen bir prompt girin.")
96
+
97
  refs = collect_refs(ref1, ref2, ref3, ref4)
98
  gen = make_generator(seed)
99
  pipe = get_pipe()
100
+
101
  result = pipe(
102
  prompt=prompt,
103
  image=refs, # None → saf t2i | list → multi-ref yönlendirmeli üretim
 
107
  guidance_scale=guidance,
108
  generator=gen,
109
  ).images[0]
110
+
111
  return result
112
+
113
+
114
  # ──────────────────────────────────────────────
115
  # Tab 2 — img2img + Karakter Referansı
116
  # ──────────────────────────────────────────────
117
+ @spaces.GPU
118
  def run_i2i(
119
  prompt: str,
120
  input_img,
 
130
  raise gr.Error("Lütfen bir prompt girin.")
131
  if input_img is None:
132
  raise gr.Error("Lütfen düzenlemek istediğiniz bir giriş görseli yükleyin.")
133
+
134
  base = to_pil(input_img)
135
  refs = collect_refs(ref1, ref2, ref3)
136
+
137
  # Tüm görseller tek liste olarak verilir:
138
  # [giriş görseli] + [karakter referansları]
139
  # Model, prompt'a göre hangi unsurları transfer edeceğine karar verir.
140
  all_images = ([base] + refs) if refs else [base]
141
+
142
  gen = make_generator(seed)
143
  pipe = get_pipe()
144
+
145
  # strength parametresi img2img gürültü oranını kontrol eder.
146
  # Flux2KleinPipeline bu parametreyi desteklemiyorsa sessizce atlanır.
147
  call_kwargs = dict(
 
158
  except TypeError:
159
  # strength desteklenmiyorsa (pipeline versiyonuna göre değişebilir)
160
  result = pipe(**call_kwargs).images[0]
161
+
162
  return result
163
+
164
+
165
  # ──────────────────────────────────────────────
166
  # Gradio Arayüzü
167
  # ──────────────────────────────────────────────
168
+
169
  CSS = """
170
  h1 { text-align: center; }
171
  .ref-row { gap: 8px !important; }
172
  footer { display: none !important; }
173
  """
174
+
175
  # Paylaşılan çözünürlük seçenekleri
176
  RESOLUTION_CHOICES = [512, 768, 1024, 1280]
177
+
178
+ with gr.Blocks(title="FLUX.2 [klein] Character Studio") as demo:
179
+
180
  gr.Markdown(
181
+ "# 🎭 FLUX.2 \\[klein\\] 9B — Character Consistency Studio\n"
182
  "> Multi-reference karakter tutarlılığı · Native multi-image support · 4-step distilled"
183
  )
184
+
185
  # ── Tab 1: Karakter Referansı ──────────────────────────────────────────
186
  with gr.Tab("🧑‍🎨 Karakter Referansı (T2I)"):
187
  gr.Markdown(
 
201
  t2i_ref2 = gr.Image(label="Ref 2", type="pil", height=140)
202
  t2i_ref3 = gr.Image(label="Ref 3", type="pil", height=140)
203
  t2i_ref4 = gr.Image(label="Ref 4", type="pil", height=140)
204
+
205
  with gr.Accordion("⚙️ Gelişmiş Ayarlar", open=False):
206
  with gr.Row():
207
  t2i_width = gr.Dropdown(RESOLUTION_CHOICES, value=1024, label="Genişlik")
 
209
  t2i_steps = gr.Slider(1, 8, value=4, step=1, label="Adım Sayısı (Steps)")
210
  t2i_guidance = gr.Slider(0.0, 5.0, value=1.0, step=0.1, label="Guidance Scale")
211
  t2i_seed = gr.Number(value=-1, label="Seed (-1 = rastgele)", precision=0)
212
+
213
  t2i_btn = gr.Button("🎨 Oluştur", variant="primary", size="lg")
214
+
215
  with gr.Column(scale=1):
216
  t2i_out = gr.Image(label="Çıktı", type="pil", height=520)
217
+
218
  t2i_btn.click(
219
  fn=run_t2i,
220
  inputs=[
 
225
  ],
226
  outputs=t2i_out,
227
  )
228
+
229
  # ── Tab 2: img2img + Referans ──────────────────────────────────────────
230
  with gr.Tab("🖼️ img2img + Referans"):
231
  gr.Markdown(
 
257
  i2i_steps = gr.Slider(1, 8, value=4, step=1, label="Adım Sayısı (Steps)")
258
  i2i_guidance = gr.Slider(0.0, 5.0, value=1.0, step=0.1, label="Guidance Scale")
259
  i2i_seed = gr.Number(value=-1, label="Seed (-1 = rastgele)", precision=0)
260
+
261
  i2i_btn = gr.Button("🖌️ Düzenle", variant="primary", size="lg")
262
+
263
  with gr.Column(scale=1):
264
  i2i_out = gr.Image(label="Çıktı", type="pil", height=520)
265
+
266
  i2i_btn.click(
267
  fn=run_i2i,
268
  inputs=[
 
274
  ],
275
  outputs=i2i_out,
276
  )
277
+
278
  # ── Bilgi Notu ──────────────────────────────────────────────────────────
279
  gr.Markdown(
280
  "---\n"
 
282
  "**Lisans:** FLUX Non-Commercial · "
283
  "**Gereksinim:** ~29 GB VRAM (A100 / H100)"
284
  )
285
+
286
  # ──────────────────────────────────────────────
287
  # Başlatma
288
  # ──────────────────────────────────────────────
289
+
290
  if __name__ == "__main__":
291
+ demo.launch(css=CSS)
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ git+https://github.com/huggingface/diffusers.git
2
+ transformers>=4.51.0
3
+ accelerate>=1.0.0
4
+ torch>=2.3.0
5
+ torchvision
6
+ gradio>=5.0.0
7
+ Pillow>=10.0.0
8
+ numpy
9
+ sentencepiece
10
+ spaces