Spaces:
Sleeping
Sleeping
Doanh Van Vu commited on
Commit ·
7083cd1
1
Parent(s): 2dfb75f
Refactor RecommendationService to remove filtering logic
Browse files- Removed the filter construction and fallback mechanism from the recommendation process, simplifying the query to Pinecone by applying no filters.
- Updated logging to reflect the changes, ensuring clarity in the absence of filters during mentor queries.
- Enhanced the overall readability and maintainability of the code by eliminating unnecessary complexity in the filtering logic.
services/recommendation_service.py
CHANGED
|
@@ -90,56 +90,18 @@ class RecommendationService:
|
|
| 90 |
embedding_time = time.perf_counter() - embedding_start
|
| 91 |
logger.info(f"[RECOMMEND] Query embedding generated in {embedding_time:.3f}s")
|
| 92 |
|
| 93 |
-
filter_start = time.perf_counter()
|
| 94 |
-
filter_dict = self._build_filter(mentee_data)
|
| 95 |
-
filter_time = time.perf_counter() - filter_start
|
| 96 |
-
logger.info(f"[RECOMMEND] Filter built in {filter_time:.3f}s: {filter_dict}")
|
| 97 |
-
|
| 98 |
pinecone_start = time.perf_counter()
|
| 99 |
similar_mentors = self.pinecone_service.query_similar(
|
| 100 |
query_vector=query_embedding,
|
| 101 |
top_k=top_k,
|
| 102 |
-
filter=
|
| 103 |
include_metadata=True
|
| 104 |
)
|
| 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
|
| 143 |
return []
|
| 144 |
|
| 145 |
metadata_start = time.perf_counter()
|
|
@@ -191,42 +153,6 @@ class RecommendationService:
|
|
| 191 |
logger.error(f"[RECOMMEND] Failed to recommend mentors after {total_time:.3f}s: {str(e)}", exc_info=True)
|
| 192 |
raise
|
| 193 |
|
| 194 |
-
def _build_filter(self, mentee_data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
| 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 |
-
|
| 230 |
def delete_mentor(self, mentor_id: str) -> bool:
|
| 231 |
try:
|
| 232 |
return self.pinecone_service.delete_mentor(mentor_id)
|
|
|
|
| 90 |
embedding_time = time.perf_counter() - embedding_start
|
| 91 |
logger.info(f"[RECOMMEND] Query embedding generated in {embedding_time:.3f}s")
|
| 92 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
pinecone_start = time.perf_counter()
|
| 94 |
similar_mentors = self.pinecone_service.query_similar(
|
| 95 |
query_vector=query_embedding,
|
| 96 |
top_k=top_k,
|
| 97 |
+
filter=None,
|
| 98 |
include_metadata=True
|
| 99 |
)
|
| 100 |
pinecone_time = time.perf_counter() - pinecone_start
|
| 101 |
+
logger.info(f"[RECOMMEND] Pinecone query completed in {pinecone_time:.3f}s: found {len(similar_mentors)} candidates (no filter applied)")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 102 |
|
| 103 |
if not similar_mentors:
|
| 104 |
+
logger.warning("[RECOMMEND] No similar mentors found, returning empty list")
|
| 105 |
return []
|
| 106 |
|
| 107 |
metadata_start = time.perf_counter()
|
|
|
|
| 153 |
logger.error(f"[RECOMMEND] Failed to recommend mentors after {total_time:.3f}s: {str(e)}", exc_info=True)
|
| 154 |
raise
|
| 155 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 156 |
def delete_mentor(self, mentor_id: str) -> bool:
|
| 157 |
try:
|
| 158 |
return self.pinecone_service.delete_mentor(mentor_id)
|