BasitAliii commited on
Commit
6f35251
·
verified ·
1 Parent(s): 0c6d894

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +95 -35
app.py CHANGED
@@ -208,6 +208,40 @@ def save_feedback(entry: Dict[str, Any]):
208
  data.append(entry)
209
  FEEDBACK_FILE.write_text(json.dumps(data, indent=2, ensure_ascii=False), encoding="utf-8")
210
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
211
  # ---------- Streamlit UI ----------
212
  st.set_page_config(page_title="AI Skill Swap", page_icon="🤝", layout="wide")
213
 
@@ -338,51 +372,77 @@ with col2:
338
  if st.button("Run AI matchmaking"):
339
  with st.spinner("Finding matches..."):
340
  current = store.find_by_username(pick)
 
 
 
 
341
 
342
- sys_ins, user_msg = make_prompt_for_matching(current, profiles, top_k)
343
  try:
 
 
344
  matches = ask_groq_for_matches(sys_ins, user_msg)
345
- except:
346
- # fallback local scoring
347
- matches = []
348
- for cand in profiles:
349
- if cand.id == current.id:
350
- continue
351
- score = 0
352
- offers_set = set(o.lower() for o in cand.offers)
353
- wants_set = set(w.lower() for w in cand.wants)
354
- cur_offers = set(o.lower() for o in current.offers)
355
- cur_wants = set(w.lower() for w in current.wants)
356
-
357
- score += len(offers_set & cur_wants) * 30
358
- score += len(cur_offers & wants_set) * 30
359
- if cand.availability and current.availability and cand.availability.lower() in current.availability.lower():
360
- score += 20
361
- if cand.preferences and current.preferences and cand.preferences.lower() in current.preferences.lower():
362
- score += 20
363
-
364
- matches.append({
365
- "id": cand.id,
366
- "username": cand.username,
367
- "score": min(100, score),
368
- "reason": "Local scoring",
369
- "avatar": cand.avatar
370
- })
371
-
372
- matches = sorted(matches, key=lambda x: x["score"], reverse=True)[:top_k]
373
 
374
  st.markdown("<div class='card'><b>Top Matches</b></div>", unsafe_allow_html=True)
375
 
376
  for m in matches:
 
 
 
377
  c1, c2 = st.columns([1, 5])
378
  with c1:
379
- if m.get("avatar") and Path(m["avatar"]).exists():
380
- st.image(m["avatar"], width=72)
 
381
  else:
382
  st.image("https://via.placeholder.com/72?text=User", width=72)
383
 
384
  with c2:
385
- st.markdown(f"### {m['username']}")
386
- st.markdown(f"**Match score:** <span class='match-score'>{m['score']}%</span>", unsafe_allow_html=True)
387
- st.progress(int(m["score"]) / 100)
388
- st.markdown("*🎉 Yass! We found a buddy to swap your skills with!*")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
  data.append(entry)
209
  FEEDBACK_FILE.write_text(json.dumps(data, indent=2, ensure_ascii=False), encoding="utf-8")
210
 
211
+ # ---------- Local matching fallback ----------
212
+ def calculate_local_matches(current: Profile, candidates: List[Profile], top_k: int = 3) -> List[Dict[str, Any]]:
213
+ matches = []
214
+ for cand in candidates:
215
+ if cand.id == current.id:
216
+ continue
217
+
218
+ score = 0
219
+ offers_set = set(o.lower() for o in cand.offers)
220
+ wants_set = set(w.lower() for w in cand.wants)
221
+ cur_offers = set(o.lower() for o in current.offers)
222
+ cur_wants = set(w.lower() for w in current.wants)
223
+
224
+ score += len(offers_set & cur_wants) * 30
225
+ score += len(cur_offers & wants_set) * 30
226
+
227
+ if cand.availability and current.availability:
228
+ if cand.availability.lower() in current.availability.lower() or current.availability.lower() in cand.availability.lower():
229
+ score += 20
230
+
231
+ if cand.preferences and current.preferences:
232
+ if cand.preferences.lower() in current.preferences.lower() or current.preferences.lower() in cand.preferences.lower():
233
+ score += 20
234
+
235
+ matches.append({
236
+ "id": cand.id,
237
+ "username": cand.username,
238
+ "score": min(100, score),
239
+ "reason": "Local scoring",
240
+ "avatar": cand.avatar
241
+ })
242
+
243
+ return sorted(matches, key=lambda x: x["score"], reverse=True)[:top_k]
244
+
245
  # ---------- Streamlit UI ----------
246
  st.set_page_config(page_title="AI Skill Swap", page_icon="🤝", layout="wide")
247
 
 
372
  if st.button("Run AI matchmaking"):
373
  with st.spinner("Finding matches..."):
374
  current = store.find_by_username(pick)
375
+
376
+ if not current:
377
+ st.error("Selected profile not found!")
378
+ st.stop()
379
 
 
380
  try:
381
+ # Try AI matching first
382
+ sys_ins, user_msg = make_prompt_for_matching(current, profiles, top_k)
383
  matches = ask_groq_for_matches(sys_ins, user_msg)
384
+
385
+ # Ensure matches have score field
386
+ for match in matches:
387
+ if "score" not in match:
388
+ match["score"] = 0
389
+ except Exception as e:
390
+ st.warning(f"AI matching failed: {e}. Using local matching...")
391
+ # Fallback to local matching
392
+ candidates = [p for p in profiles if p.id != current.id]
393
+ matches = calculate_local_matches(current, candidates, top_k)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
394
 
395
  st.markdown("<div class='card'><b>Top Matches</b></div>", unsafe_allow_html=True)
396
 
397
  for m in matches:
398
+ if not isinstance(m, dict):
399
+ continue
400
+
401
  c1, c2 = st.columns([1, 5])
402
  with c1:
403
+ avatar = m.get("avatar")
404
+ if avatar and Path(avatar).exists():
405
+ st.image(avatar, width=72)
406
  else:
407
  st.image("https://via.placeholder.com/72?text=User", width=72)
408
 
409
  with c2:
410
+ st.markdown(f"### {m.get('username', 'Unknown User')}")
411
+
412
+ # Safely get score with default value
413
+ score = m.get("score", 0)
414
+ if not isinstance(score, (int, float)):
415
+ try:
416
+ score = float(score)
417
+ except:
418
+ score = 0
419
+ score = max(0, min(100, score))
420
+
421
+ st.markdown(f"**Match score:** <span class='match-score'>{score}%</span>", unsafe_allow_html=True)
422
+ st.progress(score / 100)
423
+
424
+ reason = m.get("reason", "AI matchmaking")
425
+ st.caption(f"*{reason}*")
426
+
427
+ # Feedback button (floating)
428
+ st.markdown("""
429
+ <div class='feedback-floating' onclick="document.querySelector('.feedback-form').style.display='block'">💬</div>
430
+ """, unsafe_allow_html=True)
431
+
432
+ # Hidden feedback form
433
+ with st.sidebar:
434
+ st.markdown("---")
435
+ with st.expander("💬 Feedback"):
436
+ feedback = st.text_area("Your feedback")
437
+ if st.button("Submit Feedback"):
438
+ if feedback.strip():
439
+ save_feedback({
440
+ "timestamp": time.time(),
441
+ "feedback": feedback.strip(),
442
+ "username": st.session_state.get("username", "anonymous")
443
+ })
444
+ st.success("Thank you for your feedback!")
445
+ time.sleep(1)
446
+ st.rerun()
447
+ else:
448
+ st.warning("Please enter some feedback.")