Man-isH-07 commited on
Commit
3b2789c
·
1 Parent(s): 1469317
Files changed (2) hide show
  1. Dockerfile +23 -9
  2. app.py +43 -95
Dockerfile CHANGED
@@ -1,26 +1,40 @@
1
  # Base image with Python
2
  FROM python:3.10
3
 
4
- # Install git
5
- RUN apt-get update && apt-get install -y git
6
 
7
  WORKDIR /home/user/app
8
 
9
  # Copy all files to the container
10
  COPY . .
11
 
12
- # Clone custom node repositories with error handling and debug output
 
 
 
 
 
13
  RUN echo "Cloning ComfyUI-YoloWorld-EfficientSAM..." && \
14
- git clone https://github.com/Fannovel16/ComfyUI-YoloWorld-EfficientSAM.git custom_nodes/ComfyUI-YoloWorld-EfficientSAM || \
15
- echo "Failed to clone ComfyUI-YoloWorld-EfficientSAM"
 
 
 
16
 
17
  RUN echo "Cloning comfyui-inpaint-nodes..." && \
18
- git clone https://github.com/Acly/comfyui-inpaint-nodes.git custom_nodes/comfyui-inpaint-nodes || \
19
- echo "Failed to clone comfyui-inpaint-nodes"
 
 
 
20
 
21
  RUN echo "Cloning rgthree-comfy..." && \
22
- git clone https://github.com/rgthree/rgthree-comfy.git custom_nodes/rgthree-comfy || \
23
- echo "Failed to clone rgthree-comfy"
 
 
 
24
 
25
  # List contents of custom_nodes/ for debugging
26
  RUN echo "Contents of custom_nodes/:" && \
 
1
  # Base image with Python
2
  FROM python:3.10
3
 
4
+ # Install git and curl (for internet connectivity test)
5
+ RUN apt-get update && apt-get install -y git curl
6
 
7
  WORKDIR /home/user/app
8
 
9
  # Copy all files to the container
10
  COPY . .
11
 
12
+ # Test internet connectivity
13
+ RUN echo "Testing internet connectivity..." && \
14
+ curl -Is http://www.github.com | head -n 1 || \
15
+ (echo "Internet connectivity test failed. Check network settings." && exit 1)
16
+
17
+ # Clone custom node repositories with retries and debug output
18
  RUN echo "Cloning ComfyUI-YoloWorld-EfficientSAM..." && \
19
+ for i in 1 2 3; do \
20
+ git clone https://github.com/Fannovel16/ComfyUI-YoloWorld-EfficientSAM.git custom_nodes/ComfyUI-YoloWorld-EfficientSAM && break || \
21
+ (echo "Attempt $i failed. Retrying..." && sleep 5); \
22
+ done || \
23
+ (echo "Failed to clone ComfyUI-YoloWorld-EfficientSAM after 3 attempts" && exit 1)
24
 
25
  RUN echo "Cloning comfyui-inpaint-nodes..." && \
26
+ for i in 1 2 3; do \
27
+ git clone https://github.com/Acly/comfyui-inpaint-nodes.git custom_nodes/comfyui-inpaint-nodes && break || \
28
+ (echo "Attempt $i failed. Retrying..." && sleep 5); \
29
+ done || \
30
+ (echo "Failed to clone comfyui-inpaint-nodes after 3 attempts" && exit 1)
31
 
32
  RUN echo "Cloning rgthree-comfy..." && \
33
+ for i in 1 2 3; do \
34
+ git clone https://github.com/rgthree/rgthree-comfy.git custom_nodes/rgthree-comfy && break || \
35
+ (echo "Attempt $i failed. Retrying..." && sleep 5); \
36
+ done || \
37
+ (echo "Failed to clone rgthree-comfy after 3 attempts" && exit 1)
38
 
39
  # List contents of custom_nodes/ for debugging
40
  RUN echo "Contents of custom_nodes/:" && \
app.py CHANGED
@@ -6,20 +6,26 @@ from typing import Sequence, Mapping, Any, Union
6
  import gradio as gr
7
  from huggingface_hub import hf_hub_download
8
  import spaces
9
- import sys
10
  from comfy import model_management
11
  from nodes import NODE_CLASS_MAPPINGS
12
 
13
- import sys
 
 
 
 
 
 
 
14
  # Ensure /home/user/app/ is searched before /home/user/app/comfy/
15
  sys.path.insert(0, '/home/user/app')
16
  print("Modified sys.path:", sys.path)
17
 
18
  print("Starting Space...")
19
 
20
- os.makedirs('models/ultralytics/bbox',exist_ok=True)
21
- os.makedirs('models/inpaint',exist_ok=True)
22
- os.makedirs('models/sams',exist_ok=True)
23
 
24
  def download_model(repo_id, filename, local_dir):
25
  local_path = os.path.join(local_dir, filename)
@@ -28,43 +34,18 @@ def download_model(repo_id, filename, local_dir):
28
  else:
29
  print(f"Model {filename} already exists. Skipping download.")
30
 
31
-
32
  download_model("Acly/MAT", "MAT_Places512_G_fp16.safetensors", "models/inpaint")
33
-
34
  download_model("stabilityai/sd-vae-ft-mse-original", "vae-ft-mse-840000-ema-pruned.safetensors", "models/vae")
35
-
36
  download_model("Ultralytics/YOLOv8", "yolov8m.pt", "models/ultralytics/bbox")
37
-
38
  download_model("xingren23/comfyflow-models", "sams/sam_vit_b_01ec64.pth", "models/sams")
39
 
 
 
 
40
 
41
- # ------ JIT's Files -------- ( Added already manually )
42
-
43
- download_model("camenduru/YoloWorld-EfficientSAM", "efficient_sam_s_cpu.jit", "custom_nodes/ComfyUI-YoloWorld-EfficientSAM")
44
-
45
- download_model("camenduru/YoloWorld-EfficientSAM", "efficient_sam_s_gpu.jit", "custom_nodes/ComfyUI-YoloWorld-EfficientSAM")
46
-
47
-
48
- print("Downloaded Models")
49
 
50
  def get_value_at_index(obj: Union[Sequence, Mapping], index: int) -> Any:
51
- """Returns the value at the given index of a sequence or mapping.
52
-
53
- If the object is a sequence (like list or string), returns the value at the given index.
54
- If the object is a mapping (like a dictionary), returns the value at the index-th key.
55
-
56
- Some return a dictionary, in these cases, we look for the "results" key
57
-
58
- Args:
59
- obj (Union[Sequence, Mapping]): The object to retrieve the value from.
60
- index (int): The index of the value to retrieve.
61
-
62
- Returns:
63
- Any: The value at the given index.
64
-
65
- Raises:
66
- IndexError: If the index is out of bounds for the object and the object is not a mapping.
67
- """
68
  if obj is None:
69
  raise ValueError("Object is None, cannot retrieve index.")
70
  try:
@@ -72,37 +53,19 @@ def get_value_at_index(obj: Union[Sequence, Mapping], index: int) -> Any:
72
  except (KeyError, IndexError, TypeError):
73
  return obj.get("result", [])[index] if isinstance(obj, dict) and "result" in obj else None
74
 
75
-
76
  def find_path(name: str, path: str = None) -> str:
77
- """
78
- Recursively looks at parent folders starting from the given path until it finds the given name.
79
- Returns the path as a Path object if found, or None otherwise.
80
- """
81
- # If no path is given, use the current working directory
82
  if path is None:
83
  path = os.getcwd()
84
-
85
- # Check if the current directory contains the name
86
  if name in os.listdir(path):
87
  path_name = os.path.join(path, name)
88
  print(f"{name} found: {path_name}")
89
  return path_name
90
-
91
- # Get the parent directory
92
  parent_directory = os.path.dirname(path)
93
-
94
- # If the parent directory is the same as the current directory, we've reached the root and stop the search
95
  if parent_directory == path:
96
  return None
97
-
98
- # Recursively call the function with the parent directory
99
  return find_path(name, parent_directory)
100
 
101
-
102
  def add_comfyui_directory_to_sys_path() -> None:
103
- """
104
- Add 'ComfyUI' to the sys.path
105
- """
106
  comfyui_path = find_path("ComfyUI")
107
  if comfyui_path and os.path.isdir(comfyui_path):
108
  sys.path.append(comfyui_path)
@@ -110,7 +73,6 @@ def add_comfyui_directory_to_sys_path() -> None:
110
  else:
111
  print("⚠️ Warning: 'ComfyUI' directory not found. Ensure it is installed properly.")
112
 
113
-
114
  def add_extra_model_paths() -> None:
115
  load_extra_path_config = None
116
  try:
@@ -127,17 +89,12 @@ def add_extra_model_paths() -> None:
127
  else:
128
  print("Skipping extra model paths: config file or loader function not found.")
129
 
130
-
131
- # add_comfyui_directory_to_sys_path()
132
  add_extra_model_paths()
133
-
134
  print("Model paths added")
135
 
136
  import app_utils
137
  print("app_utils package imported:", app_utils)
138
- # print("app_utils.__path__:", app_utils.__path__)
139
 
140
- # Update debug prints
141
  print("App_utils directory contents:", os.listdir('app_utils') if os.path.exists('app_utils') else "app_utils not found")
142
  print("Parent app_utils directory contents:", os.listdir('../app_utils') if os.path.exists('../app_utils') else "parent app_utils not found")
143
  print("------------------")
@@ -154,7 +111,6 @@ try:
154
  except ImportError as e:
155
  print("Failed to import app_utils:", e)
156
 
157
- # Later in the file, update the debug prints again
158
  print("App_utils directory contents:", os.listdir('app_utils') if os.path.exists('app_utils') else "app_utils not found")
159
  print("Parent app_utils directory contents:", os.listdir('../app_utils') if os.path.exists('../app_utils') else "parent app_utils not found")
160
 
@@ -171,11 +127,6 @@ except ImportError as e:
171
  print("Failed to import utils:", e)
172
 
173
  def import_custom_nodes() -> None:
174
- """Find all custom nodes in the custom_nodes folder and add those node objects to NODE_CLASS_MAPPINGS
175
-
176
- This function sets up a new asyncio event loop, initializes the PromptServer,
177
- creates a PromptQueue, and initializes the custom nodes.
178
- """
179
  import asyncio
180
  import execution
181
  from nodes import init_extra_nodes
@@ -183,6 +134,25 @@ def import_custom_nodes() -> None:
183
  import importlib.util
184
  import traceback
185
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  # Debug: List contents of custom_nodes/
187
  print("Custom nodes directory contents:", os.listdir('custom_nodes'))
188
  for node_dir in os.listdir('custom_nodes'):
@@ -208,28 +178,16 @@ def import_custom_nodes() -> None:
208
  print(f"Failed to import {node_dir}: {str(e)}")
209
  traceback.print_exc()
210
 
211
- # Creating a new event loop and setting it as the default loop
212
- loop = asyncio.new_event_loop()
213
- asyncio.set_event_loop(loop)
214
-
215
- NODE_CLASS_MAPPINGS.clear() # Clear previous mappings
216
  print("Reloading custom nodes...")
217
-
218
- # Creating an instance of PromptServer with the loop
219
- server_instance = server.PromptServer(loop)
220
- execution.PromptQueue(server_instance)
221
-
222
- # Initializing custom nodes
223
  try:
224
  init_extra_nodes()
225
  except Exception as e:
226
  print(f"Error in init_extra_nodes(): {str(e)}")
227
  traceback.print_exc()
228
 
229
- print("Custom Nodes Loaded:", NODE_CLASS_MAPPINGS.keys())
230
-
231
 
232
- import sys
233
  print("Current working directory:", os.getcwd())
234
  print("Current directory contents:", os.listdir('.'))
235
  print("Parent directory contents:", os.listdir('..') if os.path.exists('..') else "No parent directory")
@@ -238,9 +196,8 @@ print("Utils directory contents:", os.listdir('utils') if os.path.exists('utils'
238
  print("Parent utils directory contents:", os.listdir('../utils') if os.path.exists('../utils') else "parent utils not found")
239
  import_custom_nodes()
240
 
241
-
242
  @spaces.GPU(duration=120)
243
- def object_remover(object_name, image) :
244
  import_custom_nodes()
245
  with torch.inference_mode():
246
  loadimage_1 = loadimage.load_image(image=image)
@@ -271,7 +228,6 @@ def object_remover(object_name, image) :
271
  mask=get_value_at_index(yoloworld_esam_zho_2, 1),
272
  )
273
 
274
-
275
  loadimage = NODE_CLASS_MAPPINGS["LoadImage"]()
276
 
277
  inpaint_inpaintwithmodel = NODE_CLASS_MAPPINGS["INPAINT_InpaintWithModel"]()
@@ -282,7 +238,6 @@ def object_remover(object_name, image) :
282
  mask=get_value_at_index(growmask_8, 0),
283
  )
284
 
285
-
286
  vaeencode = NODE_CLASS_MAPPINGS["VAEEncode"]()
287
  vaeencode_18 = vaeencode.encode(
288
  pixels=get_value_at_index(inpaint_inpaintwithmodel_12, 0),
@@ -322,7 +277,6 @@ def object_remover(object_name, image) :
322
  raise ValueError("Image generation failed. Check model inputs.")
323
  return "Error: Image generation failed."
324
 
325
-
326
  # Check for all required custom nodes
327
  required_nodes = [
328
  "Yoloworld_ModelLoader_Zho",
@@ -373,9 +327,8 @@ vaedecode = NODE_CLASS_MAPPINGS["VAEDecode"]()
373
  image_comparer_rgthree = NODE_CLASS_MAPPINGS["Image Comparer (rgthree)"]()
374
  saveimage = NODE_CLASS_MAPPINGS["SaveImage"]()
375
 
376
-
377
- #Add all the models that load a safetensors file
378
- model_loaders = [yoloworld_modelloader_zho_3,esam_modelloader_zho_4,inpaint_loadinpaintmodel_13,vaeloader_20]
379
 
380
  # Check which models are valid and how to best load them
381
  valid_models = [
@@ -384,24 +337,19 @@ valid_models = [
384
  if not isinstance(loader[0], dict) and not isinstance(getattr(loader[0], 'patcher', None), dict)
385
  ]
386
 
387
- #Finally loads the models
388
  device = "cuda" if torch.cuda.is_available() else "cpu"
389
  model_management.load_models_gpu(valid_models) if device == "cuda" else model_management.load_models_cpu(valid_models)
390
 
391
-
392
  with gr.Blocks() as app:
393
  gr.Markdown("# Object Remover")
394
-
395
  with gr.Column():
396
- image = gr.Image(label="Image",type="filepath")
397
  object_name = gr.Textbox(label="Obj_name")
398
  generate = gr.Button("Generate")
399
  with gr.Column():
400
  output = gr.Image(label="output")
401
- generate.click(fn=object_remover,inputs=[image,object_name],outputs=[output])
402
-
403
 
404
  print("Launching app...")
405
- app.launch(share=True, debug=True)
406
-
407
-
 
6
  import gradio as gr
7
  from huggingface_hub import hf_hub_download
8
  import spaces
 
9
  from comfy import model_management
10
  from nodes import NODE_CLASS_MAPPINGS
11
 
12
+ # Debug: Verify comfy/ directory
13
+ print("Contents of comfy/ directory:", os.listdir('comfy') if os.path.exists('comfy') else "comfy directory not found")
14
+ try:
15
+ from comfy import nodes
16
+ print("Successfully imported comfy.nodes")
17
+ except Exception as e:
18
+ print(f"Failed to import comfy.nodes: {str(e)}")
19
+
20
  # Ensure /home/user/app/ is searched before /home/user/app/comfy/
21
  sys.path.insert(0, '/home/user/app')
22
  print("Modified sys.path:", sys.path)
23
 
24
  print("Starting Space...")
25
 
26
+ os.makedirs('models/ultralytics/bbox', exist_ok=True)
27
+ os.makedirs('models/inpaint', exist_ok=True)
28
+ os.makedirs('models/sams', exist_ok=True)
29
 
30
  def download_model(repo_id, filename, local_dir):
31
  local_path = os.path.join(local_dir, filename)
 
34
  else:
35
  print(f"Model {filename} already exists. Skipping download.")
36
 
 
37
  download_model("Acly/MAT", "MAT_Places512_G_fp16.safetensors", "models/inpaint")
 
38
  download_model("stabilityai/sd-vae-ft-mse-original", "vae-ft-mse-840000-ema-pruned.safetensors", "models/vae")
 
39
  download_model("Ultralytics/YOLOv8", "yolov8m.pt", "models/ultralytics/bbox")
 
40
  download_model("xingren23/comfyflow-models", "sams/sam_vit_b_01ec64.pth", "models/sams")
41
 
42
+ # Comment out JIT file downloads since we're cloning the repository
43
+ # download_model("camenduru/YoloWorld-EfficientSAM", "efficient_sam_s_cpu.jit", "custom_nodes/ComfyUI-YoloWorld-EfficientSAM")
44
+ # download_model("camenduru/YoloWorld-EfficientSAM", "efficient_sam_s_gpu.jit", "custom_nodes/ComfyUI-YoloWorld-EfficientSAM")
45
 
46
+ print("Downloaded Models")
 
 
 
 
 
 
 
47
 
48
  def get_value_at_index(obj: Union[Sequence, Mapping], index: int) -> Any:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  if obj is None:
50
  raise ValueError("Object is None, cannot retrieve index.")
51
  try:
 
53
  except (KeyError, IndexError, TypeError):
54
  return obj.get("result", [])[index] if isinstance(obj, dict) and "result" in obj else None
55
 
 
56
  def find_path(name: str, path: str = None) -> str:
 
 
 
 
 
57
  if path is None:
58
  path = os.getcwd()
 
 
59
  if name in os.listdir(path):
60
  path_name = os.path.join(path, name)
61
  print(f"{name} found: {path_name}")
62
  return path_name
 
 
63
  parent_directory = os.path.dirname(path)
 
 
64
  if parent_directory == path:
65
  return None
 
 
66
  return find_path(name, parent_directory)
67
 
 
68
  def add_comfyui_directory_to_sys_path() -> None:
 
 
 
69
  comfyui_path = find_path("ComfyUI")
70
  if comfyui_path and os.path.isdir(comfyui_path):
71
  sys.path.append(comfyui_path)
 
73
  else:
74
  print("⚠️ Warning: 'ComfyUI' directory not found. Ensure it is installed properly.")
75
 
 
76
  def add_extra_model_paths() -> None:
77
  load_extra_path_config = None
78
  try:
 
89
  else:
90
  print("Skipping extra model paths: config file or loader function not found.")
91
 
 
 
92
  add_extra_model_paths()
 
93
  print("Model paths added")
94
 
95
  import app_utils
96
  print("app_utils package imported:", app_utils)
 
97
 
 
98
  print("App_utils directory contents:", os.listdir('app_utils') if os.path.exists('app_utils') else "app_utils not found")
99
  print("Parent app_utils directory contents:", os.listdir('../app_utils') if os.path.exists('../app_utils') else "parent app_utils not found")
100
  print("------------------")
 
111
  except ImportError as e:
112
  print("Failed to import app_utils:", e)
113
 
 
114
  print("App_utils directory contents:", os.listdir('app_utils') if os.path.exists('app_utils') else "app_utils not found")
115
  print("Parent app_utils directory contents:", os.listdir('../app_utils') if os.path.exists('../app_utils') else "parent app_utils not found")
116
 
 
127
  print("Failed to import utils:", e)
128
 
129
  def import_custom_nodes() -> None:
 
 
 
 
 
130
  import asyncio
131
  import execution
132
  from nodes import init_extra_nodes
 
134
  import importlib.util
135
  import traceback
136
 
137
+ # Creating a new event loop and setting it as the default loop
138
+ loop = asyncio.new_event_loop()
139
+ asyncio.set_event_loop(loop)
140
+
141
+ NODE_CLASS_MAPPINGS.clear() # Clear previous mappings
142
+ print("Reloading built-in nodes...")
143
+
144
+ # Creating an instance of PromptServer with the loop
145
+ server_instance = server.PromptServer(loop)
146
+ execution.PromptQueue(server_instance)
147
+
148
+ # Load built-in nodes first
149
+ try:
150
+ init_extra_nodes()
151
+ print("Built-in Nodes Loaded:", NODE_CLASS_MAPPINGS.keys())
152
+ except Exception as e:
153
+ print(f"Error loading built-in nodes: {str(e)}")
154
+ traceback.print_exc()
155
+
156
  # Debug: List contents of custom_nodes/
157
  print("Custom nodes directory contents:", os.listdir('custom_nodes'))
158
  for node_dir in os.listdir('custom_nodes'):
 
178
  print(f"Failed to import {node_dir}: {str(e)}")
179
  traceback.print_exc()
180
 
181
+ # Load custom nodes (re-run init_extra_nodes to include custom nodes)
 
 
 
 
182
  print("Reloading custom nodes...")
 
 
 
 
 
 
183
  try:
184
  init_extra_nodes()
185
  except Exception as e:
186
  print(f"Error in init_extra_nodes(): {str(e)}")
187
  traceback.print_exc()
188
 
189
+ print("All Nodes Loaded:", NODE_CLASS_MAPPINGS.keys())
 
190
 
 
191
  print("Current working directory:", os.getcwd())
192
  print("Current directory contents:", os.listdir('.'))
193
  print("Parent directory contents:", os.listdir('..') if os.path.exists('..') else "No parent directory")
 
196
  print("Parent utils directory contents:", os.listdir('../utils') if os.path.exists('../utils') else "parent utils not found")
197
  import_custom_nodes()
198
 
 
199
  @spaces.GPU(duration=120)
200
+ def object_remover(object_name, image):
201
  import_custom_nodes()
202
  with torch.inference_mode():
203
  loadimage_1 = loadimage.load_image(image=image)
 
228
  mask=get_value_at_index(yoloworld_esam_zho_2, 1),
229
  )
230
 
 
231
  loadimage = NODE_CLASS_MAPPINGS["LoadImage"]()
232
 
233
  inpaint_inpaintwithmodel = NODE_CLASS_MAPPINGS["INPAINT_InpaintWithModel"]()
 
238
  mask=get_value_at_index(growmask_8, 0),
239
  )
240
 
 
241
  vaeencode = NODE_CLASS_MAPPINGS["VAEEncode"]()
242
  vaeencode_18 = vaeencode.encode(
243
  pixels=get_value_at_index(inpaint_inpaintwithmodel_12, 0),
 
277
  raise ValueError("Image generation failed. Check model inputs.")
278
  return "Error: Image generation failed."
279
 
 
280
  # Check for all required custom nodes
281
  required_nodes = [
282
  "Yoloworld_ModelLoader_Zho",
 
327
  image_comparer_rgthree = NODE_CLASS_MAPPINGS["Image Comparer (rgthree)"]()
328
  saveimage = NODE_CLASS_MAPPINGS["SaveImage"]()
329
 
330
+ # Add all the models that load a safetensors file
331
+ model_loaders = [yoloworld_modelloader_zho_3, esam_modelloader_zho_4, inpaint_loadinpaintmodel_13, vaeloader_20]
 
332
 
333
  # Check which models are valid and how to best load them
334
  valid_models = [
 
337
  if not isinstance(loader[0], dict) and not isinstance(getattr(loader[0], 'patcher', None), dict)
338
  ]
339
 
340
+ # Finally load the models
341
  device = "cuda" if torch.cuda.is_available() else "cpu"
342
  model_management.load_models_gpu(valid_models) if device == "cuda" else model_management.load_models_cpu(valid_models)
343
 
 
344
  with gr.Blocks() as app:
345
  gr.Markdown("# Object Remover")
 
346
  with gr.Column():
347
+ image = gr.Image(label="Image", type="filepath")
348
  object_name = gr.Textbox(label="Obj_name")
349
  generate = gr.Button("Generate")
350
  with gr.Column():
351
  output = gr.Image(label="output")
352
+ generate.click(fn=object_remover, inputs=[image, object_name], outputs=[output])
 
353
 
354
  print("Launching app...")
355
+ app.launch(share=True, debug=True)