sohamnk commited on
Commit
619f2e4
Β·
verified Β·
1 Parent(s): 4282b8d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +41 -12
app.py CHANGED
@@ -1,11 +1,10 @@
1
  # --------------------------------------------------------------------------
2
- # UNIFIED AI SERVICE V3.1 (Corrected Segmentation & Logging)
3
  # --------------------------------------------------------------------------
4
  # This service uses DINOv2 for image embeddings and BGE for text embeddings.
5
- # It performs intelligent filtering before scoring.
6
- # 1. Filters by object name, date, and location hierarchy.
7
- # 2. Extracts features using BGE (text) and DINOv2 (image).
8
- # 3. Scores items based on a hybrid of text and image similarity.
9
  # --------------------------------------------------------------------------
10
 
11
  import sys
@@ -36,6 +35,12 @@ TEXT_FIELDS_TO_EMBED = ["brand", "material", "size", "colors"]
36
  SCORE_WEIGHTS = { "text_score": 0.4, "image_score": 0.6 }
37
  FINAL_SCORE_THRESHOLD = 0.5
38
 
 
 
 
 
 
 
39
  print("="*50)
40
  print("πŸš€ Initializing AI Service with DINOv2...")
41
  device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
@@ -99,7 +104,6 @@ def cosine_similarity(vec1, vec2):
99
 
100
  def segment_guided_object(image: Image.Image, object_label: str) -> Image.Image:
101
  prompt = f"a {object_label}."
102
-
103
  print(f" [Segment] Using simple prompt: '{prompt}'")
104
  image_rgb = image.convert("RGB")
105
  image_np = np.array(image_rgb)
@@ -130,13 +134,36 @@ def segment_guided_object(image: Image.Image, object_label: str) -> Image.Image:
130
 
131
  return Image.fromarray(segmented_np, 'RGB')
132
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  # ==========================================================================
134
  # --- FLASK ENDPOINTS ---
135
  # ==========================================================================
136
 
137
  @app.route('/', methods=['GET'])
138
  def health_check():
139
- return jsonify({"status": "Unified AI Service (DINOv2) is running"}), 200
140
 
141
  @app.route('/process', methods=['POST'])
142
  def process_item():
@@ -162,6 +189,12 @@ def process_item():
162
  image = Image.open(BytesIO(img_response.content))
163
 
164
  segmented_image = segment_guided_object(image, data['objectName'])
 
 
 
 
 
 
165
  embedding = get_image_embedding(segmented_image)
166
  image_embeddings.append(embedding)
167
  except Exception as e:
@@ -185,7 +218,6 @@ def compare_items():
185
  search_list = payload['searchList']
186
  print(f"\n[COMPARE] Received {len(search_list)} pre-filtered candidates for '{query_item.get('objectName')}'.")
187
 
188
- # --- SCORING ---
189
  results = []
190
  for item in search_list:
191
  item_id = item.get('_id')
@@ -207,18 +239,15 @@ def compare_items():
207
  item_img_embs = item.get('image_embeddings', [])
208
  if query_img_embs and item_img_embs:
209
  all_img_scores = []
210
- print(f" - Image Pair Scores:") # Header for detailed scores
211
  for i, q_emb in enumerate(query_img_embs):
212
  for j, i_emb in enumerate(item_img_embs):
213
- # Calculate the score for this specific pair
214
  pair_score = cosine_similarity(q_emb, i_emb)
215
- # Print the score for this pair
216
  print(f" - Query Img {i+1} vs Item Img {j+1}: {pair_score:.4f}")
217
  all_img_scores.append(pair_score)
218
  if all_img_scores:
219
  image_score = max(all_img_scores)
220
 
221
- # Use a clearer label for the max score
222
  print(f" - Max Image Score: {image_score:.4f}")
223
 
224
  # 3. Calculate Final Score
 
1
  # --------------------------------------------------------------------------
2
+ # UNIFIED AI SERVICE V3.2 (Debug Uploads & Refactored)
3
  # --------------------------------------------------------------------------
4
  # This service uses DINOv2 for image embeddings and BGE for text embeddings.
5
+ # - Filtering is handled by the Node.js backend.
6
+ # - For debugging, segmented images are uploaded to Uploadcare and the URL
7
+ # is printed to the console log.
 
8
  # --------------------------------------------------------------------------
9
 
10
  import sys
 
35
  SCORE_WEIGHTS = { "text_score": 0.4, "image_score": 0.6 }
36
  FINAL_SCORE_THRESHOLD = 0.5
37
 
38
+ # --- Load Uploadcare Credentials from Environment Variables ---
39
+ # Make sure to set this as a Secret in your Hugging Face Space settings.
40
+ UPLOADCARE_PUBLIC_KEY = os.getenv('UPLOADCARE_PUBLIC_KEY')
41
+ if not UPLOADCARE_PUBLIC_KEY:
42
+ print("⚠️ WARNING: UPLOADCARE_PUBLIC_KEY environment variable not set. Debug uploads will fail.")
43
+
44
  print("="*50)
45
  print("πŸš€ Initializing AI Service with DINOv2...")
46
  device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
 
104
 
105
  def segment_guided_object(image: Image.Image, object_label: str) -> Image.Image:
106
  prompt = f"a {object_label}."
 
107
  print(f" [Segment] Using simple prompt: '{prompt}'")
108
  image_rgb = image.convert("RGB")
109
  image_np = np.array(image_rgb)
 
134
 
135
  return Image.fromarray(segmented_np, 'RGB')
136
 
137
+ def upload_to_uploadcare(image: Image.Image) -> str:
138
+ """Uploads a PIL Image to Uploadcare and returns the CDN URL."""
139
+ if not UPLOADCARE_PUBLIC_KEY:
140
+ return "UPLOADCARE_PUBLIC_KEY not configured."
141
+
142
+ try:
143
+ # Convert PIL Image to in-memory bytes buffer
144
+ buffer = BytesIO()
145
+ image.save(buffer, format='PNG')
146
+ buffer.seek(0)
147
+
148
+ files = { 'file': ('segmented_image.png', buffer, 'image/png') }
149
+ data = { 'UPLOADCARE_PUB_KEY': UPLOADCARE_PUBLIC_KEY, 'UPLOADCARE_STORE': '1' }
150
+
151
+ response = requests.post('https://upload.uploadcare.com/base/', files=files, data=data)
152
+ response.raise_for_status()
153
+
154
+ file_uuid = response.json().get('file')
155
+ cdn_url = f"https://ucarecdn.com/{file_uuid}/"
156
+ return cdn_url
157
+ except Exception as e:
158
+ return f"Uploadcare upload failed: {e}"
159
+
160
  # ==========================================================================
161
  # --- FLASK ENDPOINTS ---
162
  # ==========================================================================
163
 
164
  @app.route('/', methods=['GET'])
165
  def health_check():
166
+ return jsonify({"status": "Unified AI Service is running"}), 200
167
 
168
  @app.route('/process', methods=['POST'])
169
  def process_item():
 
189
  image = Image.open(BytesIO(img_response.content))
190
 
191
  segmented_image = segment_guided_object(image, data['objectName'])
192
+
193
+ # --- DEBUGGING STEP: Upload segmented image and log the URL ---
194
+ debug_url = upload_to_uploadcare(segmented_image)
195
+ print(f" - 🐞 DEBUG URL: {debug_url}")
196
+ # -----------------------------------------------------------
197
+
198
  embedding = get_image_embedding(segmented_image)
199
  image_embeddings.append(embedding)
200
  except Exception as e:
 
218
  search_list = payload['searchList']
219
  print(f"\n[COMPARE] Received {len(search_list)} pre-filtered candidates for '{query_item.get('objectName')}'.")
220
 
 
221
  results = []
222
  for item in search_list:
223
  item_id = item.get('_id')
 
239
  item_img_embs = item.get('image_embeddings', [])
240
  if query_img_embs and item_img_embs:
241
  all_img_scores = []
242
+ print(f" - Image Pair Scores:")
243
  for i, q_emb in enumerate(query_img_embs):
244
  for j, i_emb in enumerate(item_img_embs):
 
245
  pair_score = cosine_similarity(q_emb, i_emb)
 
246
  print(f" - Query Img {i+1} vs Item Img {j+1}: {pair_score:.4f}")
247
  all_img_scores.append(pair_score)
248
  if all_img_scores:
249
  image_score = max(all_img_scores)
250
 
 
251
  print(f" - Max Image Score: {image_score:.4f}")
252
 
253
  # 3. Calculate Final Score