cck-0702 commited on
Commit
5780d01
·
1 Parent(s): 4dbf1db

Latest web ui that support DefectFill and DefectDiffu model run simultaneusly

Browse files
ArtiAgent - DefectDiffu/src/artiagent_orchestrator.py CHANGED
@@ -271,7 +271,7 @@ class ArtiAgentOrchestrator:
271
  # ------------------------------------------------------------------
272
 
273
  def plan(self, product_description: str, image: np.ndarray,
274
- defect_type: Optional[str] = None, max_defects: int = 3):
275
  """Agent plans defects based on product knowledge."""
276
  print(f"\\n{'='*60}")
277
  print("[Agent] Step 1: Planning defects from product description...")
@@ -285,7 +285,7 @@ class ArtiAgentOrchestrator:
285
  image,
286
  money_manager=self.money_manager,
287
  target_defect_type=defect_type,
288
- max_defects=max_defects
289
  )
290
 
291
  if plan is None:
@@ -543,7 +543,7 @@ class ArtiAgentOrchestrator:
543
  # ------------------------------------------------------------------
544
 
545
  def run(self, product_description: str, image_path: str,
546
- caption: Optional[str] = None, max_defects: int = 3,
547
  defect_type: Optional[str] = None) -> Dict:
548
  """Run the full agentic pipeline with DefectDiffu."""
549
  start_time = datetime.now()
@@ -558,10 +558,10 @@ class ArtiAgentOrchestrator:
558
 
559
  print(f"[Agent] Loaded image: {image.shape}")
560
 
561
- plan = self.plan(product_description, image, defect_type=defect_type, max_defects=max_defects)
562
 
563
  results = []
564
- defects_to_process = plan.possible_defects[:max_defects]
565
  print(f"[Agent] Processing top {len(defects_to_process)} of {len(plan.possible_defects)} planned defects")
566
 
567
  for i, defect_plan in enumerate(defects_to_process):
@@ -741,8 +741,8 @@ def main():
741
  help='Specific defect type to generate (e.g., bubble, scratch)')
742
  parser.add_argument('--output-dir', default='./defect_output', help='Output directory')
743
  parser.add_argument('--caption', default=None, help='Optional image caption')
744
- parser.add_argument('--max-defects', type=int, default=3,
745
- help='Max defects to generate (default: 3)')
746
  parser.add_argument('--device', default='cuda', help='Device (cuda/cpu)')
747
  parser.add_argument('--vlm-model', default='gemma3:12b', help='Local VLM model')
748
  parser.add_argument('--image-size', type=int, default=512,
@@ -766,7 +766,7 @@ def main():
766
  product_description=args.product_desc,
767
  image_path=args.image,
768
  caption=args.caption,
769
- max_defects=args.max_defects,
770
  defect_type=args.defect_type
771
  )
772
 
 
271
  # ------------------------------------------------------------------
272
 
273
  def plan(self, product_description: str, image: np.ndarray,
274
+ defect_type: Optional[str] = None, num_defects: int = 3):
275
  """Agent plans defects based on product knowledge."""
276
  print(f"\\n{'='*60}")
277
  print("[Agent] Step 1: Planning defects from product description...")
 
285
  image,
286
  money_manager=self.money_manager,
287
  target_defect_type=defect_type,
288
+ num_defects=num_defects
289
  )
290
 
291
  if plan is None:
 
543
  # ------------------------------------------------------------------
544
 
545
  def run(self, product_description: str, image_path: str,
546
+ caption: Optional[str] = None, num_defects: int = 3,
547
  defect_type: Optional[str] = None) -> Dict:
548
  """Run the full agentic pipeline with DefectDiffu."""
549
  start_time = datetime.now()
 
558
 
559
  print(f"[Agent] Loaded image: {image.shape}")
560
 
561
+ plan = self.plan(product_description, image, defect_type=defect_type, num_defects=num_defects)
562
 
563
  results = []
564
+ defects_to_process = plan.possible_defects[:num_defects]
565
  print(f"[Agent] Processing top {len(defects_to_process)} of {len(plan.possible_defects)} planned defects")
566
 
567
  for i, defect_plan in enumerate(defects_to_process):
 
741
  help='Specific defect type to generate (e.g., bubble, scratch)')
742
  parser.add_argument('--output-dir', default='./defect_output', help='Output directory')
743
  parser.add_argument('--caption', default=None, help='Optional image caption')
744
+ parser.add_argument('--num-defects', type=int, default=3,
745
+ help='Number of defects to generate (default: 3)')
746
  parser.add_argument('--device', default='cuda', help='Device (cuda/cpu)')
747
  parser.add_argument('--vlm-model', default='gemma3:12b', help='Local VLM model')
748
  parser.add_argument('--image-size', type=int, default=512,
 
766
  product_description=args.product_desc,
767
  image_path=args.image,
768
  caption=args.caption,
769
+ num_defects=args.num_defects,
770
  defect_type=args.defect_type
771
  )
772
 
ArtiAgent - DefectDiffu/src/pipeline/gsam_detector.py CHANGED
@@ -110,7 +110,7 @@ class GSAMDetector:
110
  device: Device to use (cuda/cpu)
111
  openai_client: OpenAI client for vocabulary generation
112
  """
113
- self.gsam_path = os.getcwd()
114
 
115
  # Set default paths if not provided
116
  if grounding_config_file is None:
 
110
  device: Device to use (cuda/cpu)
111
  openai_client: OpenAI client for vocabulary generation
112
  """
113
+ self.gsam_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
114
 
115
  # Set default paths if not provided
116
  if grounding_config_file is None:
ArtiAgent - DefectDiffu/src/pipeline/prompts.py CHANGED
@@ -134,12 +134,13 @@ def plan_defects_for_product(
134
  image,
135
  money_manager=None,
136
  target_defect_type: Optional[str] = None,
137
- max_defects: int = 3
138
  ):
139
  """
140
  Agent reasons about possible defects and outputs DefectDiffu-native plans.
141
  Each plan includes the three text prompts (c_p, c_d, c_f) and w_d/w_p scales.
142
  """
 
143
  if client is None:
144
  client = default_client
145
  base64_image = encode_image_to_base64(image)
@@ -159,7 +160,7 @@ You are given:
159
  2. A clean reference image of the product
160
  {defect_instruction}
161
 
162
- Your task is to analyze the product and propose 1-{max_defects} realistic manufacturing or handling defects.
163
 
164
  For EACH defect, you must produce THREE text prompts for the DefectDiffu diffusion model:
165
  - c_p (background prompt): "A photo of <product name>"
 
134
  image,
135
  money_manager=None,
136
  target_defect_type: Optional[str] = None,
137
+ num_defects: int = 3
138
  ):
139
  """
140
  Agent reasons about possible defects and outputs DefectDiffu-native plans.
141
  Each plan includes the three text prompts (c_p, c_d, c_f) and w_d/w_p scales.
142
  """
143
+
144
  if client is None:
145
  client = default_client
146
  base64_image = encode_image_to_base64(image)
 
160
  2. A clean reference image of the product
161
  {defect_instruction}
162
 
163
+ Your task is to analyze the product and propose {num_defects} realistic manufacturing or handling defects.
164
 
165
  For EACH defect, you must produce THREE text prompts for the DefectDiffu diffusion model:
166
  - c_p (background prompt): "A photo of <product name>"
ArtiAgent - DefectFill/src/pipeline/gsam_detector.py CHANGED
@@ -176,7 +176,7 @@ class GSAMDetector:
176
  entity_predictions = []
177
 
178
  # Use VLM to get bboxes for each entity
179
- from prompts import get_entity_bboxes
180
 
181
  all_bboxes = {} # entity -> list of bboxes
182
 
 
176
  entity_predictions = []
177
 
178
  # Use VLM to get bboxes for each entity
179
+ from pipeline.prompts import get_entity_bboxes
180
 
181
  all_bboxes = {} # entity -> list of bboxes
182
 
app.py CHANGED
@@ -25,6 +25,7 @@ import numpy as np
25
  import uuid
26
  import io
27
  import re
 
28
 
29
 
30
  # =============================================================================
@@ -78,36 +79,124 @@ if not DEFECTDIFFU_CONFIG_PATH.exists():
78
  json.dump({"ckpt_path": "", "vae_path": "", "vlm_model": "gemma3:12b"}, f, indent=2)
79
 
80
  # Setup sys.path for imports
81
- sys.path.insert(0, str(DEFECTFILL_ROOT / 'src' / 'segment_anything'))
82
- sys.path.insert(0, str(DEFECTFILL_ROOT / 'src'))
83
- sys.path.insert(0, str(DEFECTFILL_ROOT / 'pipeline'))
84
- sys.path.insert(0, str(DEFECTFILL_ROOT))
85
- sys.path.insert(0, str(DEFECTDIFFU_ROOT))
86
- sys.path.insert(0, str(DEFECTDIFFU_ROOT / 'pipeline'))
87
-
88
- # DefectFill imports
89
- try:
90
- from artiagent_orchestrator import ArtiAgentOrchestrator as DefectFillOrchestrator
91
- from align_image_to_reference import align_image_to_reference
92
- from detect_similar_product import check_product_training_status
93
- except Exception as e:
94
- print(f"[WARNING] DefectFill imports failed: {e}")
95
- DefectFillOrchestrator = None
96
- align_image_to_reference = None
97
- check_product_training_status = None
98
-
99
- # DefectDiffu imports
100
- try:
101
- from artiagent_orchestrator import ArtiAgentOrchestrator as DefectDiffuOrchestrator
102
- except Exception as e:
103
- print(f"[WARNING] DefectDiffu imports failed: {e}")
104
- DefectDiffuOrchestrator = None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
 
106
  from flask import Flask, render_template, request, jsonify, send_from_directory
107
  from flask_cors import CORS
108
 
109
  app = Flask(__name__, template_folder=str(BASE_DIR / "templates"), static_folder=str(BASE_DIR / "static"))
110
- app.config["MAX_CONTENT_LENGTH"] = 32 * 1024 * 1024 # 32MB upload limit
111
  CORS(app)
112
 
113
  # =============================================================================
@@ -263,7 +352,7 @@ def run_generation_job(job_id, params, mode='defectfill'):
263
  result = orchestrator.run(
264
  product_description=params['product_desc'],
265
  image_path=clean_path,
266
- max_defects=params['num_defects'],
267
  defect_type=params['defect_type']
268
  )
269
 
 
25
  import uuid
26
  import io
27
  import re
28
+ import importlib.util
29
 
30
 
31
  # =============================================================================
 
79
  json.dump({"ckpt_path": "", "vae_path": "", "vlm_model": "gemma3:12b"}, f, indent=2)
80
 
81
  # Setup sys.path for imports
82
+ # sys.path.insert(0, str(DEFECTFILL_ROOT / 'src' / 'segment_anything'))
83
+ # sys.path.insert(0, str(DEFECTFILL_ROOT / 'src'))
84
+ # sys.path.insert(0, str(DEFECTFILL_ROOT / 'pipeline'))
85
+ # sys.path.insert(0, str(DEFECTFILL_ROOT))
86
+ # sys.path.insert(0, str(DEFECTDIFFU_ROOT))
87
+ # sys.path.insert(0, str(DEFECTDIFFU_ROOT / 'src'))
88
+ # sys.path.insert(0, str(DEFECTDIFFU_ROOT / 'pipeline'))
89
+
90
+ # =============================================================================
91
+ # Dynamic Import Helpers (avoid module name collisions)
92
+ # =============================================================================
93
+
94
+ def load_orchestrator_from_path(module_path, class_name="ArtiAgentOrchestrator", extra_paths=None):
95
+ """
96
+ Dynamically import a class from a Python file, temporarily adding
97
+ extra_paths to sys.path so that the module's internal imports
98
+ resolve to the correct project.
99
+ """
100
+ if not module_path.exists():
101
+ print(f"[ERROR] Module file not found: {module_path}")
102
+ return None
103
+
104
+ original_sys_path = sys.path[:] # save current state
105
+
106
+ try:
107
+ # Insert project‑specific paths at the front
108
+ if extra_paths:
109
+ for p in reversed(extra_paths): # reverse to keep the given order
110
+ p_str = str(p)
111
+ if p_str not in sys.path:
112
+ sys.path.insert(0, p_str)
113
+
114
+ # Also ensure the module's own directory is available
115
+ module_dir = module_path.parent
116
+ if module_dir not in sys.path:
117
+ sys.path.insert(0, str(module_dir))
118
+
119
+ # Use a unique module name to avoid caching collisions
120
+ module_id = f"_dynamic_{class_name}_{uuid.uuid4().hex[:8]}"
121
+ spec = importlib.util.spec_from_file_location(module_id, str(module_path))
122
+ module = importlib.util.module_from_spec(spec)
123
+ spec.loader.exec_module(module)
124
+
125
+ cls = getattr(module, class_name, None)
126
+ if cls is None:
127
+ print(f"[ERROR] Class '{class_name}' not found in {module_path}")
128
+ return cls
129
+
130
+ except Exception as e:
131
+ print(f"[ERROR] Failed to load {module_path}: {e}")
132
+ traceback.print_exc()
133
+ return None
134
+
135
+ finally:
136
+ # Restore original sys.path to avoid leaking
137
+ sys.path[:] = original_sys_path
138
+
139
+
140
+ # DefectFill imports — load directly from file to avoid sys.path collision with DefectFill
141
+ extra_paths_df = [
142
+ DEFECTFILL_ROOT / 'src' / 'segment_anything',
143
+ DEFECTFILL_ROOT / 'src',
144
+ DEFECTFILL_ROOT / 'pipeline',
145
+ DEFECTFILL_ROOT,
146
+ ]
147
+
148
+ df_orchestrator_path = DEFECTFILL_ROOT / "src" / "artiagent_orchestrator.py"
149
+ DefectFillOrchestrator = load_orchestrator_from_path(
150
+ df_orchestrator_path,
151
+ "ArtiAgentOrchestrator",
152
+ extra_paths_df
153
+ )
154
+ print("[INFO] DefectFill orchestrator is ready.", flush=True)
155
+
156
+
157
+ # DefectDiffu imports — load directly from file to avoid name collision with DefectDiffu
158
+ extra_paths_dd = [
159
+ DEFECTDIFFU_ROOT / 'src',
160
+ DEFECTDIFFU_ROOT / "engine" / "DefectDiffu",
161
+ DEFECTDIFFU_ROOT,
162
+ ]
163
+
164
+ dd_orchestrator_path = DEFECTDIFFU_ROOT / 'src' / "artiagent_orchestrator.py"
165
+ DefectDiffuOrchestrator = load_orchestrator_from_path(
166
+ dd_orchestrator_path,
167
+ "ArtiAgentOrchestrator",
168
+ extra_paths_dd
169
+ )
170
+ print("[INFO] DefectDiffu orchestrator is ready.")
171
+
172
+ def load_helper_from_path(module_path, function_name):
173
+ # Use a generic loader (can reuse load_orchestrator_from_path with no class)
174
+ # But for functions, you can load the module and extract the function.
175
+ original_sys_path = sys.path[:]
176
+ try:
177
+ # Add DefectFill paths (or pass as extra_paths)
178
+ sys.path.insert(0, str(DEFECTFILL_ROOT / 'src'))
179
+ sys.path.insert(0, str(DEFECTFILL_ROOT))
180
+ spec = importlib.util.spec_from_file_location(f"_helper_{uuid.uuid4().hex[:8]}", str(module_path))
181
+ module = importlib.util.module_from_spec(spec)
182
+ spec.loader.exec_module(module)
183
+ return getattr(module, function_name, None)
184
+ finally:
185
+ sys.path[:] = original_sys_path
186
+
187
+ # Usage:
188
+ align_image_to_reference = load_helper_from_path(
189
+ DEFECTFILL_ROOT / 'src' / 'align_image_to_reference.py', 'align_image_to_reference'
190
+ )
191
+ check_product_training_status = load_helper_from_path(
192
+ DEFECTFILL_ROOT / 'src' / 'detect_similar_product.py', 'check_product_training_status'
193
+ )
194
 
195
  from flask import Flask, render_template, request, jsonify, send_from_directory
196
  from flask_cors import CORS
197
 
198
  app = Flask(__name__, template_folder=str(BASE_DIR / "templates"), static_folder=str(BASE_DIR / "static"))
199
+ app.config["MAX_CONTENT_LENGTH"] = 100 * 1024 * 1024 # 100MB upload limit
200
  CORS(app)
201
 
202
  # =============================================================================
 
352
  result = orchestrator.run(
353
  product_description=params['product_desc'],
354
  image_path=clean_path,
355
+ num_defects=params['num_defects'],
356
  defect_type=params['defect_type']
357
  )
358
 
config/defectdiffu_config.json CHANGED
@@ -1,5 +1,5 @@
1
  {
2
- "ckpt_path": "C:\\Users\\admin_mtds\\OneDrive\\Desktop\\ChinKuan\\ArtiAgent - Defect\\engine\\DefectDiffu\\checkpoint_old-4\\model_300.pth",
3
- "vae_path": "C:\\Users\\admin_mtds\\OneDrive\\Desktop\\ChinKuan\\ArtiAgent - Defect\\engine\\DefectDiffu\\checkpoints\\sd-vae-ft-mse",
4
  "vlm_model": "gemma3:12b"
5
  }
 
1
  {
2
+ "ckpt_path": "C:\\Users\\admin_mtds\\OneDrive\\Desktop\\ChinKuan\\ArtiAgent - latest WebUI\\ArtiAgent - DefectDiffu\\engine\\DefectDiffu\\checkpoint_old-4\\model_300.pth",
3
+ "vae_path": "C:\\Users\\admin_mtds\\OneDrive\\Desktop\\ChinKuan\\ArtiAgent - latest WebUI\\ArtiAgent - DefectDiffu\\engine\\DefectDiffu\\checkpoints\\sd-vae-ft-mse",
4
  "vlm_model": "gemma3:12b"
5
  }