Spaces:
Sleeping
Sleeping
Doanh Van Vu
commited on
Commit
·
f879018
1
Parent(s):
ff5d801
Implement fallback filtering in RecommendationService for mentor queries
Browse files- Added logic to handle cases where no mentors are found with strict filters (rating/availability) by introducing a fallback mechanism that relaxes these constraints.
- Enhanced logging to provide detailed information about the filtering process and fallback attempts, improving traceability and debugging capabilities.
- Updated the filter construction to include logging for each filter applied based on mentee data.
services/recommendation_service.py
CHANGED
|
@@ -105,8 +105,41 @@ class RecommendationService:
|
|
| 105 |
pinecone_time = time.perf_counter() - pinecone_start
|
| 106 |
logger.info(f"[RECOMMEND] Pinecone query completed in {pinecone_time:.3f}s: found {len(similar_mentors)} candidates")
|
| 107 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 108 |
if not similar_mentors:
|
| 109 |
-
logger.warning("[RECOMMEND] No similar mentors found, returning empty list")
|
| 110 |
return []
|
| 111 |
|
| 112 |
metadata_start = time.perf_counter()
|
|
@@ -162,24 +195,35 @@ class RecommendationService:
|
|
| 162 |
filter_dict = {}
|
| 163 |
|
| 164 |
if mentee_data.get("min_rating"):
|
| 165 |
-
|
|
|
|
|
|
|
| 166 |
|
| 167 |
if mentee_data.get("require_availability"):
|
| 168 |
filter_dict["has_availability"] = True
|
|
|
|
| 169 |
|
| 170 |
if mentee_data.get("skill_ids"):
|
| 171 |
-
|
|
|
|
|
|
|
| 172 |
|
| 173 |
if mentee_data.get("domain_ids"):
|
| 174 |
-
|
|
|
|
|
|
|
| 175 |
|
| 176 |
if mentee_data.get("career_id"):
|
| 177 |
-
|
|
|
|
|
|
|
| 178 |
|
| 179 |
if mentee_data.get("status"):
|
| 180 |
filter_dict["status"] = str(mentee_data["status"])
|
|
|
|
| 181 |
else:
|
| 182 |
filter_dict["status"] = "ACTIVATED"
|
|
|
|
| 183 |
|
| 184 |
return filter_dict if filter_dict else None
|
| 185 |
|
|
|
|
| 105 |
pinecone_time = time.perf_counter() - pinecone_start
|
| 106 |
logger.info(f"[RECOMMEND] Pinecone query completed in {pinecone_time:.3f}s: found {len(similar_mentors)} candidates")
|
| 107 |
|
| 108 |
+
if not similar_mentors and filter_dict:
|
| 109 |
+
has_strict_filters = "rating" in filter_dict or "has_availability" in filter_dict
|
| 110 |
+
|
| 111 |
+
if has_strict_filters:
|
| 112 |
+
logger.warning(f"[RECOMMEND] No results with strict filter (rating/availability), trying fallback with relaxed filter")
|
| 113 |
+
logger.info(f"[RECOMMEND] Original filter: {filter_dict}")
|
| 114 |
+
|
| 115 |
+
fallback_filter = {}
|
| 116 |
+
if mentee_data.get("skill_ids"):
|
| 117 |
+
fallback_filter["skill_ids"] = {"$in": [str(int(id)) for id in mentee_data["skill_ids"]]}
|
| 118 |
+
if mentee_data.get("domain_ids"):
|
| 119 |
+
fallback_filter["domain_ids"] = {"$in": [str(int(id)) for id in mentee_data["domain_ids"]]}
|
| 120 |
+
if mentee_data.get("career_id"):
|
| 121 |
+
fallback_filter["career_id"] = int(mentee_data["career_id"])
|
| 122 |
+
if mentee_data.get("status"):
|
| 123 |
+
fallback_filter["status"] = str(mentee_data["status"])
|
| 124 |
+
else:
|
| 125 |
+
fallback_filter["status"] = "ACTIVATED"
|
| 126 |
+
|
| 127 |
+
logger.info(f"[RECOMMEND] Fallback filter (removed rating/availability constraints): {fallback_filter}")
|
| 128 |
+
|
| 129 |
+
fallback_start = time.perf_counter()
|
| 130 |
+
similar_mentors = self.pinecone_service.query_similar(
|
| 131 |
+
query_vector=query_embedding,
|
| 132 |
+
top_k=top_k,
|
| 133 |
+
filter=fallback_filter if fallback_filter else None,
|
| 134 |
+
include_metadata=True
|
| 135 |
+
)
|
| 136 |
+
fallback_time = time.perf_counter() - fallback_start
|
| 137 |
+
logger.info(f"[RECOMMEND] Fallback query completed in {fallback_time:.3f}s: found {len(similar_mentors)} candidates")
|
| 138 |
+
else:
|
| 139 |
+
logger.warning(f"[RECOMMEND] No results found even without strict filters")
|
| 140 |
+
|
| 141 |
if not similar_mentors:
|
| 142 |
+
logger.warning("[RECOMMEND] No similar mentors found after fallback, returning empty list")
|
| 143 |
return []
|
| 144 |
|
| 145 |
metadata_start = time.perf_counter()
|
|
|
|
| 195 |
filter_dict = {}
|
| 196 |
|
| 197 |
if mentee_data.get("min_rating"):
|
| 198 |
+
min_rating = float(mentee_data["min_rating"])
|
| 199 |
+
filter_dict["rating"] = {"$gte": min_rating}
|
| 200 |
+
logger.info(f"[RECOMMEND] Adding rating filter: >= {min_rating}")
|
| 201 |
|
| 202 |
if mentee_data.get("require_availability"):
|
| 203 |
filter_dict["has_availability"] = True
|
| 204 |
+
logger.info(f"[RECOMMEND] Adding availability filter: has_availability=True")
|
| 205 |
|
| 206 |
if mentee_data.get("skill_ids"):
|
| 207 |
+
skill_ids = [str(int(id)) for id in mentee_data["skill_ids"]]
|
| 208 |
+
filter_dict["skill_ids"] = {"$in": skill_ids}
|
| 209 |
+
logger.info(f"[RECOMMEND] Adding skill_ids filter: {skill_ids}")
|
| 210 |
|
| 211 |
if mentee_data.get("domain_ids"):
|
| 212 |
+
domain_ids = [str(int(id)) for id in mentee_data["domain_ids"]]
|
| 213 |
+
filter_dict["domain_ids"] = {"$in": domain_ids}
|
| 214 |
+
logger.info(f"[RECOMMEND] Adding domain_ids filter: {domain_ids}")
|
| 215 |
|
| 216 |
if mentee_data.get("career_id"):
|
| 217 |
+
career_id = int(mentee_data["career_id"])
|
| 218 |
+
filter_dict["career_id"] = career_id
|
| 219 |
+
logger.info(f"[RECOMMEND] Adding career_id filter: {career_id}")
|
| 220 |
|
| 221 |
if mentee_data.get("status"):
|
| 222 |
filter_dict["status"] = str(mentee_data["status"])
|
| 223 |
+
logger.info(f"[RECOMMEND] Adding status filter: {mentee_data['status']}")
|
| 224 |
else:
|
| 225 |
filter_dict["status"] = "ACTIVATED"
|
| 226 |
+
logger.info(f"[RECOMMEND] Adding default status filter: ACTIVATED")
|
| 227 |
|
| 228 |
return filter_dict if filter_dict else None
|
| 229 |
|