Spaces:
Sleeping
Sleeping
Doanh Van Vu
commited on
Commit
·
69934b0
1
Parent(s):
7083cd1
Refactor mentor availability handling across services
Browse files- Removed the `available_slots` and `has_availability` fields from the MentorUpsertRequest and RecommendationRequest models, streamlining the data structure.
- Updated the PineconeService and RecommendationService to eliminate references to availability metrics in logging and processing.
- Simplified scoring logic in the rerank_mentors function by removing the availability score calculation, enhancing performance and clarity.
- Adjusted the mentor text building process to exclude available slots information, improving the output format.
- models/schemas.py +0 -3
- services/pinecone_service.py +0 -2
- services/recommendation_service.py +0 -2
- test_api.py +0 -2
- utils/scoring.py +3 -20
- utils/text_builder.py +0 -4
models/schemas.py
CHANGED
|
@@ -45,13 +45,11 @@ class MentorUpsertRequest(BaseModel):
|
|
| 45 |
rating: Optional[float] = Field(None, ge=0.0, le=5.0)
|
| 46 |
total_ratings: Optional[int] = Field(None, ge=0)
|
| 47 |
session_count: Optional[int] = Field(None, ge=0)
|
| 48 |
-
available_slots: Optional[int] = Field(None, ge=0)
|
| 49 |
schedules: Optional[List[Union[ScheduleDto, Dict[str, Any]]]] = None
|
| 50 |
career_id: Optional[int] = None
|
| 51 |
skill_ids: Optional[List[int]] = None
|
| 52 |
domain_ids: Optional[List[int]] = None
|
| 53 |
status: Optional[str] = "ACTIVATED"
|
| 54 |
-
has_availability: Optional[bool] = False
|
| 55 |
|
| 56 |
class MentorUpsertResponse(BaseModel):
|
| 57 |
success: bool
|
|
@@ -67,7 +65,6 @@ class RecommendationRequest(BaseModel):
|
|
| 67 |
availability: Optional[str] = None
|
| 68 |
preferred_availability: Optional[str] = None
|
| 69 |
min_rating: Optional[float] = Field(None, ge=0.0, le=5.0)
|
| 70 |
-
require_availability: Optional[bool] = False
|
| 71 |
skill_ids: Optional[List[int]] = None
|
| 72 |
domain_ids: Optional[List[int]] = None
|
| 73 |
career_id: Optional[int] = None
|
|
|
|
| 45 |
rating: Optional[float] = Field(None, ge=0.0, le=5.0)
|
| 46 |
total_ratings: Optional[int] = Field(None, ge=0)
|
| 47 |
session_count: Optional[int] = Field(None, ge=0)
|
|
|
|
| 48 |
schedules: Optional[List[Union[ScheduleDto, Dict[str, Any]]]] = None
|
| 49 |
career_id: Optional[int] = None
|
| 50 |
skill_ids: Optional[List[int]] = None
|
| 51 |
domain_ids: Optional[List[int]] = None
|
| 52 |
status: Optional[str] = "ACTIVATED"
|
|
|
|
| 53 |
|
| 54 |
class MentorUpsertResponse(BaseModel):
|
| 55 |
success: bool
|
|
|
|
| 65 |
availability: Optional[str] = None
|
| 66 |
preferred_availability: Optional[str] = None
|
| 67 |
min_rating: Optional[float] = Field(None, ge=0.0, le=5.0)
|
|
|
|
| 68 |
skill_ids: Optional[List[int]] = None
|
| 69 |
domain_ids: Optional[List[int]] = None
|
| 70 |
career_id: Optional[int] = None
|
services/pinecone_service.py
CHANGED
|
@@ -135,9 +135,7 @@ class PineconeService:
|
|
| 135 |
f"score={match.score:.4f}, "
|
| 136 |
f"rating={metadata.get('rating', 'N/A')}, "
|
| 137 |
f"total_ratings={metadata.get('total_ratings', 0)}, "
|
| 138 |
-
f"available_slots={metadata.get('available_slots', 0)}, "
|
| 139 |
f"session_count={metadata.get('session_count', 0)}, "
|
| 140 |
-
f"has_availability={metadata.get('has_availability', False)}, "
|
| 141 |
f"status={metadata.get('status', 'N/A')}, "
|
| 142 |
f"career_id={metadata.get('career_id', 'N/A')}, "
|
| 143 |
f"skill_ids={metadata.get('skill_ids', [])}, "
|
|
|
|
| 135 |
f"score={match.score:.4f}, "
|
| 136 |
f"rating={metadata.get('rating', 'N/A')}, "
|
| 137 |
f"total_ratings={metadata.get('total_ratings', 0)}, "
|
|
|
|
| 138 |
f"session_count={metadata.get('session_count', 0)}, "
|
|
|
|
| 139 |
f"status={metadata.get('status', 'N/A')}, "
|
| 140 |
f"career_id={metadata.get('career_id', 'N/A')}, "
|
| 141 |
f"skill_ids={metadata.get('skill_ids', [])}, "
|
services/recommendation_service.py
CHANGED
|
@@ -45,8 +45,6 @@ class RecommendationService:
|
|
| 45 |
"rating": safe_float(mentor_data.get("rating"), 0.0),
|
| 46 |
"total_ratings": safe_int(mentor_data.get("total_ratings"), 0),
|
| 47 |
"session_count": safe_int(mentor_data.get("session_count"), 0),
|
| 48 |
-
"available_slots": safe_int(mentor_data.get("available_slots"), 0),
|
| 49 |
-
"has_availability": bool(mentor_data.get("has_availability", False)),
|
| 50 |
"career_id": safe_int(mentor_data.get("career_id")) if mentor_data.get("career_id") else None,
|
| 51 |
"status": str(mentor_data.get("status") or "ACTIVATED"),
|
| 52 |
"mentor_text": mentor_text
|
|
|
|
| 45 |
"rating": safe_float(mentor_data.get("rating"), 0.0),
|
| 46 |
"total_ratings": safe_int(mentor_data.get("total_ratings"), 0),
|
| 47 |
"session_count": safe_int(mentor_data.get("session_count"), 0),
|
|
|
|
|
|
|
| 48 |
"career_id": safe_int(mentor_data.get("career_id")) if mentor_data.get("career_id") else None,
|
| 49 |
"status": str(mentor_data.get("status") or "ACTIVATED"),
|
| 50 |
"mentor_text": mentor_text
|
test_api.py
CHANGED
|
@@ -18,7 +18,6 @@ def test_recommend():
|
|
| 18 |
{"id": 1, "name": "Web Development"}
|
| 19 |
],
|
| 20 |
"min_rating": 4.0,
|
| 21 |
-
"require_availability": True,
|
| 22 |
"skill_ids": [1, 2],
|
| 23 |
"domain_ids": [1],
|
| 24 |
"top_k": 30,
|
|
@@ -63,7 +62,6 @@ def test_recommend():
|
|
| 63 |
if "metadata" in mentor:
|
| 64 |
meta = mentor["metadata"]
|
| 65 |
print(f" Rating: {meta.get('rating', 'N/A')}")
|
| 66 |
-
print(f" Available Slots: {meta.get('available_slots', 0)}")
|
| 67 |
|
| 68 |
if "query_text" in result:
|
| 69 |
print(f"\nQuery Text: {result['query_text']}")
|
|
|
|
| 18 |
{"id": 1, "name": "Web Development"}
|
| 19 |
],
|
| 20 |
"min_rating": 4.0,
|
|
|
|
| 21 |
"skill_ids": [1, 2],
|
| 22 |
"domain_ids": [1],
|
| 23 |
"top_k": 30,
|
|
|
|
| 62 |
if "metadata" in mentor:
|
| 63 |
meta = mentor["metadata"]
|
| 64 |
print(f" Rating: {meta.get('rating', 'N/A')}")
|
|
|
|
| 65 |
|
| 66 |
if "query_text" in result:
|
| 67 |
print(f"\nQuery Text: {result['query_text']}")
|
utils/scoring.py
CHANGED
|
@@ -28,12 +28,8 @@ def rerank_mentors(
|
|
| 28 |
semantic_score = reranker_score * settings.SEMANTIC_WEIGHT
|
| 29 |
|
| 30 |
rating_score = _calculate_rating_score(metadata.get("rating", 0.0))
|
| 31 |
-
availability_score = _calculate_availability_score(metadata.get("available_slots", 0))
|
| 32 |
|
| 33 |
-
rule_based_score =
|
| 34 |
-
rating_score * 0.5 +
|
| 35 |
-
availability_score * 0.5
|
| 36 |
-
) * settings.RULE_BASED_WEIGHT
|
| 37 |
|
| 38 |
final_score = semantic_score + rule_based_score
|
| 39 |
|
|
@@ -43,8 +39,7 @@ def rerank_mentors(
|
|
| 43 |
reranker_score,
|
| 44 |
metadata,
|
| 45 |
mentee_data,
|
| 46 |
-
rating_score
|
| 47 |
-
availability_score
|
| 48 |
)
|
| 49 |
|
| 50 |
scored_mentors.append({
|
|
@@ -75,20 +70,12 @@ def _calculate_rating_score(rating: float) -> float:
|
|
| 75 |
return 0.0
|
| 76 |
return min(rating / 5.0, 1.0)
|
| 77 |
|
| 78 |
-
def _calculate_availability_score(available_slots: int) -> float:
|
| 79 |
-
if available_slots <= 0:
|
| 80 |
-
return 0.0
|
| 81 |
-
if available_slots >= 10:
|
| 82 |
-
return 1.0
|
| 83 |
-
return min(available_slots / 10.0, 1.0)
|
| 84 |
-
|
| 85 |
|
| 86 |
def _generate_reason(
|
| 87 |
reranker_score: float,
|
| 88 |
metadata: Dict[str, Any],
|
| 89 |
mentee_data: Dict[str, Any],
|
| 90 |
-
rating_score: float
|
| 91 |
-
availability_score: float
|
| 92 |
) -> str:
|
| 93 |
reasons = []
|
| 94 |
|
|
@@ -103,10 +90,6 @@ def _generate_reason(
|
|
| 103 |
elif rating >= 4.0:
|
| 104 |
reasons.append("High ratings")
|
| 105 |
|
| 106 |
-
available_slots = metadata.get("available_slots", 0)
|
| 107 |
-
if available_slots > 0:
|
| 108 |
-
reasons.append("Has available slots")
|
| 109 |
-
|
| 110 |
if not reasons:
|
| 111 |
reasons.append("Good overall match")
|
| 112 |
|
|
|
|
| 28 |
semantic_score = reranker_score * settings.SEMANTIC_WEIGHT
|
| 29 |
|
| 30 |
rating_score = _calculate_rating_score(metadata.get("rating", 0.0))
|
|
|
|
| 31 |
|
| 32 |
+
rule_based_score = rating_score * settings.RULE_BASED_WEIGHT
|
|
|
|
|
|
|
|
|
|
| 33 |
|
| 34 |
final_score = semantic_score + rule_based_score
|
| 35 |
|
|
|
|
| 39 |
reranker_score,
|
| 40 |
metadata,
|
| 41 |
mentee_data,
|
| 42 |
+
rating_score
|
|
|
|
| 43 |
)
|
| 44 |
|
| 45 |
scored_mentors.append({
|
|
|
|
| 70 |
return 0.0
|
| 71 |
return min(rating / 5.0, 1.0)
|
| 72 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 73 |
|
| 74 |
def _generate_reason(
|
| 75 |
reranker_score: float,
|
| 76 |
metadata: Dict[str, Any],
|
| 77 |
mentee_data: Dict[str, Any],
|
| 78 |
+
rating_score: float
|
|
|
|
| 79 |
) -> str:
|
| 80 |
reasons = []
|
| 81 |
|
|
|
|
| 90 |
elif rating >= 4.0:
|
| 91 |
reasons.append("High ratings")
|
| 92 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
if not reasons:
|
| 94 |
reasons.append("Good overall match")
|
| 95 |
|
utils/text_builder.py
CHANGED
|
@@ -99,10 +99,6 @@ def build_mentor_text(mentor_data: Dict[str, Any]) -> str:
|
|
| 99 |
if session_count:
|
| 100 |
parts.append(f"Sessions Conducted: {session_count}")
|
| 101 |
|
| 102 |
-
available_slots = mentor_data.get("available_slots", 0)
|
| 103 |
-
if available_slots:
|
| 104 |
-
parts.append(f"Available Slots: {available_slots}")
|
| 105 |
-
|
| 106 |
schedules = mentor_data.get("schedules", [])
|
| 107 |
if schedules:
|
| 108 |
schedule_summary = _build_schedule_summary(schedules)
|
|
|
|
| 99 |
if session_count:
|
| 100 |
parts.append(f"Sessions Conducted: {session_count}")
|
| 101 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 102 |
schedules = mentor_data.get("schedules", [])
|
| 103 |
if schedules:
|
| 104 |
schedule_summary = _build_schedule_summary(schedules)
|