matrice-analytics 0.1.54__py3-none-any.whl → 0.1.56__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of matrice-analytics might be problematic. Click here for more details.

@@ -175,11 +175,14 @@ class EmbeddingManager:
175
175
  """Load all staff embeddings from API and cache them."""
176
176
  if not self.face_client:
177
177
  self.logger.error("Face client not available for loading staff embeddings")
178
+ print("ERROR: Face client not available for loading staff embeddings")
178
179
  return False
179
180
 
180
181
  try:
181
182
  self.logger.info("Loading staff embeddings from API...")
183
+ print("=============== LOADING STAFF EMBEDDINGS FROM API ===============")
182
184
  response = await self.face_client.get_all_staff_embeddings()
185
+ print(f"API RESPONSE TYPE: {type(response)}, IS_LIST: {isinstance(response, list)}, LEN: {len(response) if isinstance(response, list) else 'N/A'}")
183
186
 
184
187
  # Robust response handling: accept dict with data or raw list
185
188
  embeddings_data: List[Dict[str, Any]] = []
@@ -205,23 +208,58 @@ class EmbeddingManager:
205
208
 
206
209
  self.staff_embeddings = []
207
210
  embeddings_list = []
208
-
211
+ expected_dim: Optional[int] = None
212
+ dims_observed: List[int] = []
213
+ mismatch_examples: List[Tuple[str, int]] = [] # (staffId, dim)
214
+
209
215
  for item in embeddings_data:
210
- # if not item.get("isActive", True): # TODO: Check what is isActive
211
- # continue
212
-
216
+ # Skip inactive if provided
217
+ if isinstance(item, dict) and item.get("isActive") is False:
218
+ continue
219
+
220
+ raw_emb = []
221
+ try:
222
+ raw_emb = item.get("embedding", []) if isinstance(item, dict) else []
223
+ except Exception:
224
+ raw_emb = []
225
+ # Record observed dimension for debugging
226
+ try:
227
+ dims_observed.append(len(raw_emb) if isinstance(raw_emb, list) else 0)
228
+ except Exception:
229
+ dims_observed.append(0)
230
+
231
+ # Validate and coerce embedding list
232
+ if not isinstance(raw_emb, list) or len(raw_emb) == 0:
233
+ continue
234
+ try:
235
+ # Ensure numeric float32 list
236
+ clean_emb = [float(v) for v in raw_emb]
237
+ except Exception:
238
+ continue
239
+
240
+ # Dimension consistency
241
+ if expected_dim is None:
242
+ expected_dim = len(clean_emb)
243
+ if len(clean_emb) != expected_dim:
244
+ # Collect a few examples to aid debugging
245
+ try:
246
+ mismatch_examples.append((str(item.get("staffId", "")), len(clean_emb)))
247
+ except Exception:
248
+ mismatch_examples.append(("", len(clean_emb)))
249
+ self.logger.warning(f"Skipping embedding with mismatched dimension: got {len(clean_emb)} expected {expected_dim}")
250
+ continue
251
+
213
252
  staff_embedding = StaffEmbedding(
214
- embedding_id=item.get("embeddingId", ""),
215
- staff_id=item.get("staffId", ""),
216
- embedding=item.get("embedding", []),
217
- employee_id=str(item.get("employeeId", "")),
218
- staff_details=item.get("staffDetails", {}),
219
- is_active=item.get("isActive", True)
253
+ embedding_id=(item.get("embeddingId", "") if isinstance(item, dict) else ""),
254
+ staff_id=(item.get("staffId", "") if isinstance(item, dict) else ""),
255
+ embedding=clean_emb,
256
+ employee_id=str(item.get("employeeId", "")) if isinstance(item, dict) else "",
257
+ staff_details=(item.get("staffDetails", {}) if isinstance(item, dict) else {}),
258
+ is_active=(item.get("isActive", True) if isinstance(item, dict) else True)
220
259
  )
221
-
222
- if staff_embedding.embedding: # Only add if embedding exists
223
- self.staff_embeddings.append(staff_embedding)
224
- embeddings_list.append(staff_embedding.embedding)
260
+
261
+ self.staff_embeddings.append(staff_embedding)
262
+ embeddings_list.append(clean_emb)
225
263
 
226
264
  # Create numpy matrix for fast similarity computation (thread-safe)
227
265
  with self._embeddings_lock:
@@ -234,12 +272,31 @@ class EmbeddingManager:
234
272
 
235
273
  self.embedding_metadata = self.staff_embeddings.copy()
236
274
  self.staff_embeddings_last_update = time.time()
237
- self.logger.info(f"Successfully loaded and cached {len(self.staff_embeddings)} staff embeddings")
238
- self.logger.debug(f"Embeddings matrix shape: {self.embeddings_matrix.shape}")
275
+ self.logger.info(f"Successfully loaded and cached {len(self.staff_embeddings)} staff embeddings (dim={self.embeddings_matrix.shape[1]})")
276
+ print(f"=============== SUCCESS: LOADED {len(self.staff_embeddings)} EMBEDDINGS, MATRIX SHAPE: {self.embeddings_matrix.shape} ===============")
277
+ try:
278
+ # Quick sanity metrics
279
+ row0_sum = float(np.sum(self.embeddings_matrix[0])) if self.embeddings_matrix.shape[0] > 0 else 0.0
280
+ row0_norm = float(np.linalg.norm(self.embeddings_matrix[0])) if self.embeddings_matrix.shape[0] > 0 else 0.0
281
+ print(f"SANITY CHECK: row0_sum={row0_sum:.4f}, row0_norm={row0_norm:.4f} (should be ~1.0 after normalization)")
282
+ self.logger.debug(f"Embeddings matrix shape: {self.embeddings_matrix.shape}, dtype={self.embeddings_matrix.dtype}, row0_sum={row0_sum:.4f}")
283
+ except Exception as e:
284
+ print(f"ERROR in sanity check: {e}")
239
285
  return True
240
286
  else:
241
- self.logger.warning("No active staff embeddings found in API response")
242
- return False
287
+ # Build diagnostics and raise to stop pipeline early with actionable info
288
+ dims_summary: Dict[int, int] = {}
289
+ for d in dims_observed:
290
+ dims_summary[d] = dims_summary.get(d, 0) + 1
291
+ error_msg = (
292
+ f"No valid staff embeddings loaded. Observed dimension distribution: {dims_summary}. "
293
+ f"Expected_dim={expected_dim}. Mismatch examples (staffId, dim): {mismatch_examples[:5]}"
294
+ )
295
+ self.logger.error(error_msg)
296
+ print(f"=============== ERROR: NO VALID EMBEDDINGS ===============")
297
+ print(f"ERROR: {error_msg}")
298
+ print(f"=============== STOPPING PIPELINE ===============")
299
+ raise RuntimeError(f"Failed to load staff embeddings due to dimension mismatch. Observed dims: {dims_summary}")
243
300
 
244
301
  except Exception as e:
245
302
  self.logger.error(f"Error loading staff embeddings: {e}", exc_info=True)
@@ -281,6 +338,7 @@ class EmbeddingManager:
281
338
  """Find best matching staff member using optimized matrix operations (thread-safe)."""
282
339
  with self._embeddings_lock:
283
340
  if self.embeddings_matrix is None or len(self.embedding_metadata) == 0:
341
+ print(f"ERROR: _find_best_local_match - embeddings_matrix is None={self.embeddings_matrix is None}, metadata_len={len(self.embedding_metadata)}")
284
342
  return None
285
343
 
286
344
  # Create local copies to avoid issues with concurrent modifications
@@ -292,6 +350,11 @@ class EmbeddingManager:
292
350
 
293
351
  try:
294
352
  query_array = np.array(query_embedding, dtype=np.float32).reshape(1, -1)
353
+ # Dimension check
354
+ if embeddings_matrix.shape[1] != query_array.shape[1]:
355
+ self.logger.warning(f"Query embedding dim mismatch: query={query_array.shape[1]} staff={embeddings_matrix.shape[1]}")
356
+ print(f"ERROR: DIMENSION MISMATCH - query={query_array.shape[1]} staff={embeddings_matrix.shape[1]}")
357
+ return None
295
358
 
296
359
  # Normalize query embedding
297
360
  query_norm = np.linalg.norm(query_array)
@@ -327,6 +390,9 @@ class EmbeddingManager:
327
390
  return 0.0
328
391
  try:
329
392
  query_array = np.array(query_embedding, dtype=np.float32).reshape(1, -1)
393
+ if embeddings_matrix.shape[1] != query_array.shape[1]:
394
+ print(f"ERROR: get_best_similarity DIMENSION MISMATCH - query={query_array.shape[1]} staff={embeddings_matrix.shape[1]}")
395
+ return 0.0
330
396
  qn = np.linalg.norm(query_array)
331
397
  if qn == 0:
332
398
  return 0.0
@@ -1603,11 +1603,11 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
1603
1603
  human_text_lines.append(f"\tRecognized: {face_summary.get('session_totals',{}).get('total_recognized', 0)}")
1604
1604
  human_text_lines.append(f"\tUnknown: {face_summary.get('session_totals',{}).get('total_unknown', 0)}")
1605
1605
  # Additional counts similar to compare_similarity HUD
1606
- try:
1607
- human_text_lines.append(f"\tCurrent Faces (detections): {total_detections}")
1608
- human_text_lines.append(f"\tTotal Unique Tracks: {cumulative_total}")
1609
- except Exception:
1610
- pass
1606
+ # try:
1607
+ # human_text_lines.append(f"\tCurrent Faces (detections): {total_detections}")
1608
+ # human_text_lines.append(f"\tTotal Unique Tracks: {cumulative_total}")
1609
+ # except Exception:
1610
+ # pass
1611
1611
 
1612
1612
  human_text = "\n".join(human_text_lines)
1613
1613
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: matrice_analytics
3
- Version: 0.1.54
3
+ Version: 0.1.56
4
4
  Summary: Common server utilities for Matrice.ai services
5
5
  Author-email: "Matrice.ai" <dipendra@matrice.ai>
6
6
  License-Expression: MIT
@@ -28,8 +28,8 @@ matrice_analytics/post_processing/core/config.py,sha256=uyxWndO-DE9PeGD_h5K3TeB0
28
28
  matrice_analytics/post_processing/core/config_utils.py,sha256=QuAS-_JKSoNOtfUWgr7Alf_wsqODzN2rHlQu-cHRK0s,34311
29
29
  matrice_analytics/post_processing/face_reg/__init__.py,sha256=yntaiGlW9vdjBpPZQXNuovALihJPzRlFyUE88l3MhBA,1364
30
30
  matrice_analytics/post_processing/face_reg/compare_similarity.py,sha256=NlFc8b2a74k0PqSFAbuM_fUbA1BT3pr3VUgvSqRpJzQ,23396
31
- matrice_analytics/post_processing/face_reg/embedding_manager.py,sha256=lt6BSRylvCzPVsKBpYBrDBZ7-LkJOf_aGbsl_5422Ps,37525
32
- matrice_analytics/post_processing/face_reg/face_recognition.py,sha256=ILkQumMY2ij_QrhJxzLifOv_q5rXh7N4mW94hr6EcgQ,103585
31
+ matrice_analytics/post_processing/face_reg/embedding_manager.py,sha256=euZdFxslvEStli7pcUrBhyvJ-FR5uUGjU7HkrQ2XIfU,41940
32
+ matrice_analytics/post_processing/face_reg/face_recognition.py,sha256=CkJaf1M4Ah7YSoxOjSVoSPqAp912QkrVS0v2cLeWMCQ,103595
33
33
  matrice_analytics/post_processing/face_reg/face_recognition_client.py,sha256=eF2NYju1uWKXhILndI1rh4_VhWrKSGidui2jjbPQXgM,27596
34
34
  matrice_analytics/post_processing/face_reg/people_activity_logging.py,sha256=vZbIvkK1h3h58ROeF0_ygF3lqr19O2h5222bN8XyIis,13675
35
35
  matrice_analytics/post_processing/ocr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -189,8 +189,8 @@ matrice_analytics/post_processing/utils/format_utils.py,sha256=UTF7A5h9j0_S12xH9
189
189
  matrice_analytics/post_processing/utils/geometry_utils.py,sha256=BWfdM6RsdJTTLR1GqkWfdwpjMEjTCJyuBxA4zVGKdfk,9623
190
190
  matrice_analytics/post_processing/utils/smoothing_utils.py,sha256=78U-yucAcjUiZ0NIAc9NOUSIT0PWP1cqyIPA_Fdrjp0,14699
191
191
  matrice_analytics/post_processing/utils/tracking_utils.py,sha256=rWxuotnJ3VLMHIBOud2KLcu4yZfDp7hVPWUtNAq_2xw,8288
192
- matrice_analytics-0.1.54.dist-info/licenses/LICENSE.txt,sha256=_uQUZpgO0mRYL5-fPoEvLSbNnLPv6OmbeEDCHXhK6Qc,1066
193
- matrice_analytics-0.1.54.dist-info/METADATA,sha256=1RfM8nWJEoj9BnNP4ehKraPM8ZSReG7D2dZ8JYjxqew,14378
194
- matrice_analytics-0.1.54.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
195
- matrice_analytics-0.1.54.dist-info/top_level.txt,sha256=STAPEU-e-rWTerXaspdi76T_eVRSrEfFpURSP7_Dt8E,18
196
- matrice_analytics-0.1.54.dist-info/RECORD,,
192
+ matrice_analytics-0.1.56.dist-info/licenses/LICENSE.txt,sha256=_uQUZpgO0mRYL5-fPoEvLSbNnLPv6OmbeEDCHXhK6Qc,1066
193
+ matrice_analytics-0.1.56.dist-info/METADATA,sha256=plXBTb5-QrbiN9-4ui3W5hj6bo15-ka3tgANA0Pxzpk,14378
194
+ matrice_analytics-0.1.56.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
195
+ matrice_analytics-0.1.56.dist-info/top_level.txt,sha256=STAPEU-e-rWTerXaspdi76T_eVRSrEfFpURSP7_Dt8E,18
196
+ matrice_analytics-0.1.56.dist-info/RECORD,,