subhan971 commited on
Commit
db3a13b
Β·
verified Β·
1 Parent(s): 7d7a37f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +15 -11
app.py CHANGED
@@ -170,11 +170,8 @@ def build_categorical_features(profiles):
170
 
171
  for col in CATEGORICAL_COLS:
172
  try:
173
- # Get all values and sort for deterministic ordering
174
  unique_vals = sorted(set(p[col] for p in profiles if p[col]))
175
- # Create value-to-index mapping (0-based, 0 reserved for unknown)
176
  val_to_idx = {val: idx+1 for idx, val in enumerate(unique_vals)}
177
- # Encode each profile's value as integer (0 for unknown/missing)
178
  encoded = np.array([val_to_idx.get(p[col], 0) for p in profiles])
179
  cat_features.append(encoded.reshape(-1, 1))
180
  except Exception as e:
@@ -196,7 +193,6 @@ def build_text_features(profiles, vectorizers=None):
196
  try:
197
  corpus = [p[col] for p in profiles]
198
 
199
- # Always create fresh vectorizer to match current corpus
200
  tfidf = TfidfVectorizer(
201
  max_features=30,
202
  stop_words='english',
@@ -235,7 +231,7 @@ def build_feature_matrix(profiles, vectorizers=None):
235
  features.append(ages_norm)
236
  logger.debug(f"Age features: {ages_norm.shape}")
237
 
238
- # 2. Categorical features (one-hot encoded)
239
  logger.debug("Building categorical features...")
240
  cat_feat = build_categorical_features(profiles)
241
  if cat_feat.size > 0:
@@ -266,7 +262,6 @@ async def refresh_cache():
266
  try:
267
  logger.info("πŸ”„ Refreshing profile cache...")
268
 
269
- # Fetch profiles
270
  raw_profiles = await fetch_profiles_paginated()
271
 
272
  if not raw_profiles or len(raw_profiles) < 5:
@@ -274,7 +269,6 @@ async def refresh_cache():
274
  cache.error_message = f"Only {len(raw_profiles)} profiles, need at least 5"
275
  return False
276
 
277
- # Preprocess
278
  logger.info("Preprocessing profiles...")
279
  profiles = []
280
  for p in raw_profiles:
@@ -292,7 +286,6 @@ async def refresh_cache():
292
 
293
  logger.info(f"Preprocessed {len(profiles)} profiles")
294
 
295
- # Build features
296
  logger.info("Building feature matrix...")
297
  X, vectorizers, scaler = build_feature_matrix(profiles, cache.tfidf_vectorizers)
298
 
@@ -301,7 +294,6 @@ async def refresh_cache():
301
  cache.error_message = "Feature matrix is empty"
302
  return False
303
 
304
- # Update cache
305
  cache.profiles = profiles
306
  cache.feature_matrix = X
307
  cache.profile_ids = [p['id'] for p in profiles]
@@ -397,7 +389,6 @@ async def recommend_query(
397
  Returns raw list: [{user_id, score, reasons}, ...]
398
  """
399
  matches = await _compute_matches(user_id, top_n, min_score)
400
- # Transform to AiMatchService format
401
  return [
402
  {
403
  "user_id": m['id'],
@@ -480,7 +471,7 @@ async def _compute_matches(user_id: str, top_n: int, min_score: float):
480
  # Top N
481
  top_positions = np.argsort(sims)[::-1][:top_n]
482
 
483
- # Build result list with full candidate data + score
484
  result = []
485
  for pos in top_positions:
486
  score = float(sims[pos])
@@ -498,7 +489,20 @@ async def _compute_matches(user_id: str, top_n: int, min_score: float):
498
  'score': score
499
  })
500
 
 
501
  logger.info(f"βœ“ Generated {len(result)} recommendations for {user_id}")
 
 
 
 
 
 
 
 
 
 
 
 
502
  return result
503
 
504
 
 
170
 
171
  for col in CATEGORICAL_COLS:
172
  try:
 
173
  unique_vals = sorted(set(p[col] for p in profiles if p[col]))
 
174
  val_to_idx = {val: idx+1 for idx, val in enumerate(unique_vals)}
 
175
  encoded = np.array([val_to_idx.get(p[col], 0) for p in profiles])
176
  cat_features.append(encoded.reshape(-1, 1))
177
  except Exception as e:
 
193
  try:
194
  corpus = [p[col] for p in profiles]
195
 
 
196
  tfidf = TfidfVectorizer(
197
  max_features=30,
198
  stop_words='english',
 
231
  features.append(ages_norm)
232
  logger.debug(f"Age features: {ages_norm.shape}")
233
 
234
+ # 2. Categorical features
235
  logger.debug("Building categorical features...")
236
  cat_feat = build_categorical_features(profiles)
237
  if cat_feat.size > 0:
 
262
  try:
263
  logger.info("πŸ”„ Refreshing profile cache...")
264
 
 
265
  raw_profiles = await fetch_profiles_paginated()
266
 
267
  if not raw_profiles or len(raw_profiles) < 5:
 
269
  cache.error_message = f"Only {len(raw_profiles)} profiles, need at least 5"
270
  return False
271
 
 
272
  logger.info("Preprocessing profiles...")
273
  profiles = []
274
  for p in raw_profiles:
 
286
 
287
  logger.info(f"Preprocessed {len(profiles)} profiles")
288
 
 
289
  logger.info("Building feature matrix...")
290
  X, vectorizers, scaler = build_feature_matrix(profiles, cache.tfidf_vectorizers)
291
 
 
294
  cache.error_message = "Feature matrix is empty"
295
  return False
296
 
 
297
  cache.profiles = profiles
298
  cache.feature_matrix = X
299
  cache.profile_ids = [p['id'] for p in profiles]
 
389
  Returns raw list: [{user_id, score, reasons}, ...]
390
  """
391
  matches = await _compute_matches(user_id, top_n, min_score)
 
392
  return [
393
  {
394
  "user_id": m['id'],
 
471
  # Top N
472
  top_positions = np.argsort(sims)[::-1][:top_n]
473
 
474
+ # Build result list
475
  result = []
476
  for pos in top_positions:
477
  score = float(sims[pos])
 
489
  'score': score
490
  })
491
 
492
+ # ── Display recommendations in terminal ──
493
  logger.info(f"βœ“ Generated {len(result)} recommendations for {user_id}")
494
+ logger.info(f"β”Œ{'─'*60}")
495
+ logger.info(f"β”‚ Requesting user : {user['full_name']} ({user['gender']}, {user['age']})")
496
+ logger.info(f"β”œ{'─'*60}")
497
+ for rank, r in enumerate(result, 1):
498
+ logger.info(
499
+ f"β”‚ #{rank:<2} {r['full_name']:<25} "
500
+ f"Age: {r['age']:<4} "
501
+ f"City: {r['city']:<15} "
502
+ f"Score: {r['score']*100:.1f}%"
503
+ )
504
+ logger.info(f"β””{'─'*60}")
505
+
506
  return result
507
 
508