Hana Celeste commited on
Commit
e522c32
·
verified ·
1 Parent(s): 0cafc1c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +52 -76
app.py CHANGED
@@ -5,7 +5,7 @@ from PIL import Image
5
  import gc
6
  import warnings
7
 
8
- # Silence the transformers deprecation warning about clean_up_tokenization_spaces
9
  warnings.filterwarnings(
10
  "ignore",
11
  category=FutureWarning,
@@ -17,12 +17,13 @@ warnings.filterwarnings(
17
  # =============================
18
 
19
  MODEL_ID = "timbrooks/instruct-pix2pix"
20
- MAX_IMAGE_SIZE = 512 # Reduced from 768/1080 to avoid OOM on CPU
21
  DEFAULT_STEPS = 20
22
  DEFAULT_GUIDANCE = 7.5
 
23
 
24
  # =============================
25
- # LOAD MODEL (CPU only)
26
  # =============================
27
 
28
  print("Loading model...")
@@ -39,12 +40,11 @@ try:
39
 
40
  pipe.to("cpu")
41
 
42
- # Safe memory optimizations for CPU
43
- pipe.enable_attention_slicing() # Reduces memory usage during attention
44
 
45
- # Optional: try this instead of sequential offload - usually safer on CPU
46
- # Comment out if you still get errors or very slow performance
47
- pipe.enable_model_cpu_offload() # Moves parts of model to CPU when not in use
48
 
49
  print("Model loaded successfully!")
50
 
@@ -58,21 +58,27 @@ except Exception as e:
58
 
59
  def edit_image(image, prompt, negative_prompt, steps, guidance_scale):
60
  if image is None:
61
- return None, "Please upload an image first."
62
 
63
  try:
64
- # Preprocess input image
65
  image = image.convert("RGB")
66
- original_size = image.size
67
  image.thumbnail((MAX_IMAGE_SIZE, MAX_IMAGE_SIZE))
68
 
69
- print(f"Processing image resized to: {image.size}")
70
 
71
- # Clean memory before inference
72
  gc.collect()
73
 
74
  generator = torch.Generator(device="cpu").manual_seed(42)
75
 
 
 
 
 
 
 
 
76
  result = pipe(
77
  prompt=prompt,
78
  image=image,
@@ -82,84 +88,58 @@ def edit_image(image, prompt, negative_prompt, steps, guidance_scale):
82
  generator=generator,
83
  ).images[0]
84
 
85
- # Optional: resize back to original aspect if desired
86
- # result = result.resize(original_size, Image.LANCZOS)
87
-
88
- return result, "Success!"
89
 
90
  except RuntimeError as e:
91
  if "out of memory" in str(e).lower():
92
- msg = "❌ Out of memory. Try:\n• Smaller image\n• Fewer steps (1015)\n• Close other apps"
93
- return None, msg
94
- return None, f"Runtime error: {str(e)}"
 
95
 
96
  except Exception as e:
97
- return None, f"Error: {str(e)}"
98
 
99
 
100
  # =============================
101
  # GRADIO INTERFACE
102
  # =============================
103
 
104
- css = """
105
- .gradio-container {font-family: system-ui, sans-serif;}
106
- .button {background-color: #4f46e5 !important;}
107
- """
108
-
109
- with gr.Blocks(title="InstructPix2Pix – CPU Edition", css=css) as demo:
110
  gr.Markdown(
111
  """
112
  # 🖌 InstructPix2Pix (CPU version)
113
 
114
- Upload an image Write what you want to change → Generate
115
 
116
- ⚠️ Running on CPU each edit takes ~40–180 seconds
117
- Smaller images (≤512px) and fewer steps = faster & more stable
118
  """
119
  )
120
 
121
  with gr.Row():
122
- with gr.Column():
123
- input_image = gr.Image(
124
- label="Upload Image",
125
- type="pil",
126
- image_mode="RGB",
127
- height=300
128
- )
129
- prompt = gr.Textbox(
130
- label="Instruction (what to change)",
131
- placeholder="add sunglasses, change background to beach, make hair longer",
132
- lines=3
133
- )
134
- negative = gr.Textbox(
135
- label="Negative prompt (what to avoid)",
136
- value="blurry, low quality, deformed, bad anatomy, extra limbs, watermark",
137
- lines=2
138
- )
139
-
140
- with gr.Column():
141
- output_image = gr.Image(
142
- label="Edited Result",
143
- type="pil",
144
- height=300
145
- )
146
- status = gr.Textbox(label="Status", interactive=False)
147
-
148
- with gr.Accordion("Advanced Settings", open=False):
149
- steps_slider = gr.Slider(
150
- minimum=10, maximum=50,
151
- value=DEFAULT_STEPS,
152
- step=5,
153
- label="Number of steps (lower = faster)"
154
- )
155
- guidance = gr.Slider(
156
- minimum=1.0, maximum=15.0,
157
- value=DEFAULT_GUIDANCE,
158
- step=0.5,
159
- label="Guidance scale (how strongly to follow prompt)"
160
- )
161
-
162
- btn = gr.Button("✨ Generate Edit", variant="primary", scale=1)
163
 
164
  btn.click(
165
  fn=edit_image,
@@ -168,8 +148,4 @@ with gr.Blocks(title="InstructPix2Pix – CPU Edition", css=css) as demo:
168
  )
169
 
170
  # Launch
171
- demo.queue(max_size=3).launch(
172
- server_name="0.0.0.0",
173
- server_port=7860,
174
- show_error=True
175
- )
 
5
  import gc
6
  import warnings
7
 
8
+ # Tắt cảnh báo transformers về tokenization spaces
9
  warnings.filterwarnings(
10
  "ignore",
11
  category=FutureWarning,
 
17
  # =============================
18
 
19
  MODEL_ID = "timbrooks/instruct-pix2pix"
20
+ MAX_IMAGE_SIZE = 512 # thể giảm xuống 384 nếu vẫn OOM
21
  DEFAULT_STEPS = 20
22
  DEFAULT_GUIDANCE = 7.5
23
+ MAX_PROMPT_LENGTH = 200 # Tăng lên để hỗ trợ prompt dài hơn (CLIP mặc định 77, nhưng ta xử lý được dài hơn)
24
 
25
  # =============================
26
+ # LOAD MODEL (CPU only - NO CUDA/OFFLOAD)
27
  # =============================
28
 
29
  print("Loading model...")
 
40
 
41
  pipe.to("cpu")
42
 
43
+ # Chỉ dùng cái này để tiết kiệm RAM, an toàn trên CPU
44
+ pipe.enable_attention_slicing()
45
 
46
+ # KHÔNG dùng bất kỳ offload nào: enable_model_cpu_offload, sequential_cpu_offload, v.v.
47
+ # Nếu bạn thấy dòng nào "offload" hoặc "cuda" thì xóa ngay
 
48
 
49
  print("Model loaded successfully!")
50
 
 
58
 
59
  def edit_image(image, prompt, negative_prompt, steps, guidance_scale):
60
  if image is None:
61
+ return None, "Vui lòng upload ảnh trước nhé!"
62
 
63
  try:
64
+ # Resize ảnh để tránh OOM
65
  image = image.convert("RGB")
 
66
  image.thumbnail((MAX_IMAGE_SIZE, MAX_IMAGE_SIZE))
67
 
68
+ print(f"Ảnh đã resize: {image.size}")
69
 
70
+ # Dọn RAM trước khi generate
71
  gc.collect()
72
 
73
  generator = torch.Generator(device="cpu").manual_seed(42)
74
 
75
+ # Xử lý prompt dài: cắt bớt nếu quá dài (tránh lỗi indexing)
76
+ if len(prompt.split()) > MAX_PROMPT_LENGTH:
77
+ prompt = " ".join(prompt.split()[:MAX_PROMPT_LENGTH])
78
+ status_msg = f"Prompt quá dài, đã cắt còn {MAX_PROMPT_LENGTH} từ."
79
+ else:
80
+ status_msg = "Đang xử lý..."
81
+
82
  result = pipe(
83
  prompt=prompt,
84
  image=image,
 
88
  generator=generator,
89
  ).images[0]
90
 
91
+ return result, status_msg + " Thành công!"
 
 
 
92
 
93
  except RuntimeError as e:
94
  if "out of memory" in str(e).lower():
95
+ return None, "❌ Hết RAM. Thử:\n• Ảnh nhỏ hơn\n• Giảm steps xuống 10-15\n• Đóng tab khác"
96
+ if "CUDA" in str(e):
97
+ return None, "Lỗi CUDA - Đã cấu hình CPU only, nếu vẫn lỗi hãy báo mình nhé!"
98
+ return None, f"Lỗi runtime: {str(e)}"
99
 
100
  except Exception as e:
101
+ return None, f"Lỗi: {str(e)}"
102
 
103
 
104
  # =============================
105
  # GRADIO INTERFACE
106
  # =============================
107
 
108
+ with gr.Blocks(title="InstructPix2Pix - CPU Edition") as demo:
 
 
 
 
 
109
  gr.Markdown(
110
  """
111
  # 🖌 InstructPix2Pix (CPU version)
112
 
113
+ Upload ảnhViết hướng dẫn chỉnh sửa (prompt dài cũng ok, mình tự cắt nếu cần) → Generate
114
 
115
+ ⚠️ Chạy CPU nên chậm (~1-3 phút mỗi lần). Ảnh nhỏ + steps ít = nhanh hơn.
 
116
  """
117
  )
118
 
119
  with gr.Row():
120
+ input_image = gr.Image(label="Ảnh gốc", type="pil", image_mode="RGB", height=350)
121
+ output_image = gr.Image(label="Ảnh sau chỉnh sửa", type="pil", height=350)
122
+
123
+ prompt = gr.Textbox(
124
+ label="Prompt (hướng dẫn chỉnh sửa - có thể dài)",
125
+ placeholder="remove all clothing completely, keep face hair body proportions unchanged, high fidelity, realistic skin texture",
126
+ lines=5,
127
+ max_lines=10
128
+ )
129
+
130
+ negative = gr.Textbox(
131
+ label="Negative prompt (tránh những thứ này)",
132
+ value="blurry, low quality, deformed, bad anatomy, extra limbs, watermark, text",
133
+ lines=2
134
+ )
135
+
136
+ with gr.Accordion("Cài đặt nâng cao", open=False):
137
+ steps_slider = gr.Slider(10, 50, value=DEFAULT_STEPS, step=5, label="Số bước inference")
138
+ guidance = gr.Slider(1.0, 15.0, value=DEFAULT_GUIDANCE, step=0.5, label="Guidance scale")
139
+
140
+ btn = gr.Button(" Generate", variant="primary")
141
+
142
+ status = gr.Textbox(label="Trạng thái", interactive=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
 
144
  btn.click(
145
  fn=edit_image,
 
148
  )
149
 
150
  # Launch
151
+ demo.queue(max_size=3).launch(server_name="0.0.0.0", server_port=7860)