Skip to content

Commit 678b232

Browse files
Merge pull request #22 from Riminder/feat/add-scoring-searching-profile-validation
Feat: add validation for profile searching & scoring in utils
2 parents 51711de + 39c992b commit 678b232

4 files changed

Lines changed: 156 additions & 0 deletions

File tree

hrflow/schemas.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,12 @@ class Experience(BaseModel):
241241
tasks: t.Optional[t.List[GeneralEntitySchema]] = Field(
242242
None, description="List of tasks of the Experience."
243243
)
244+
languages: t.Optional[t.List[GeneralEntitySchema]] = Field(
245+
None, description="List of spoken languages of the profile"
246+
)
247+
interests: t.Optional[t.List[GeneralEntitySchema]] = Field(
248+
None, description="List of interests of the Experience."
249+
)
244250

245251

246252
class Education(BaseModel):
@@ -274,6 +280,12 @@ class Education(BaseModel):
274280
tasks: t.Optional[t.List[GeneralEntitySchema]] = Field(
275281
None, description="List of tasks of the Education."
276282
)
283+
languages: t.Optional[t.List[GeneralEntitySchema]] = Field(
284+
None, description="List of spoken languages of the profile"
285+
)
286+
interests: t.Optional[t.List[GeneralEntitySchema]] = Field(
287+
None, description="List of interests of the Experience."
288+
)
277289

278290

279291
class Attachment(BaseModel):

hrflow/utils/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
# noqa: F401
22
from .evaluation import generate_parsing_evaluation_report
3+
from .scoring import is_valid_for_scoring
4+
from .searching import is_valid_for_searching
35
from .storing import get_all_jobs, get_all_profiles

hrflow/utils/scoring.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import typing as t
2+
3+
from ..schemas import Education, Experience, HrFlowProfile
4+
from .searching import is_valid_for_searching
5+
6+
7+
def is_valid_experiences_for_scoring(
8+
experience_list: t.Optional[t.List[Experience]],
9+
) -> bool:
10+
"""
11+
Check if a list of experiences is valid for scoring
12+
13+
Args:
14+
experience_list: <list>
15+
List of experiences to check
16+
Return:
17+
<bool> True if the list of experiences is valid for
18+
scoring, False otherwise
19+
"""
20+
for experience in experience_list:
21+
if experience.title:
22+
return True
23+
24+
return False
25+
26+
27+
def is_valid_educations_for_scoring(
28+
education_list: t.Optional[t.List[Education]],
29+
) -> bool:
30+
"""
31+
Check if a list of educations is valid for scoring
32+
33+
Args:
34+
education_list: <list>
35+
List of educations to check
36+
Return:
37+
<bool> True if the list of educations is valid for
38+
scoring, False otherwise
39+
"""
40+
for education in education_list:
41+
if education.title or education.school:
42+
return True
43+
return False
44+
45+
46+
def is_valid_for_scoring(
47+
profile: t.Union[t.Dict, HrFlowProfile],
48+
) -> bool:
49+
"""
50+
Check if a profile is valid for scoring
51+
52+
Based on the following schemas https://developers.hrflow.ai/docs/profiles-scoring
53+
54+
Args:
55+
client: <Hrflow>
56+
Hrflow client
57+
profile: <dict> or <HrFlowProfile>
58+
Profile to check
59+
Return:
60+
<bool> True if the profile is valid for scoring,
61+
False otherwise
62+
"""
63+
if isinstance(profile, dict):
64+
profile = HrFlowProfile.parse_obj(profile)
65+
66+
if not isinstance(profile, HrFlowProfile):
67+
raise ValueError("profile must be a dict or a HrFlowProfile object")
68+
69+
return is_valid_for_searching(profile) and (
70+
is_valid_experiences_for_scoring(profile.experiences)
71+
or is_valid_educations_for_scoring(profile.educations)
72+
or bool(profile.summary)
73+
or bool(profile.skills)
74+
or bool(profile.tasks)
75+
)

hrflow/utils/searching.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import typing as t
2+
3+
from ..schemas import HrFlowProfile, ProfileInfo
4+
5+
6+
def is_valid_info_for_searching(info: ProfileInfo) -> bool:
7+
"""
8+
Check if the info part of a profile is valid for searching
9+
10+
Based on the following schemas https://developers.hrflow.ai/docs/profiles-searching
11+
12+
Args:
13+
info: <ProfileInfo>
14+
Info part of the profile
15+
"""
16+
if not isinstance(info, ProfileInfo):
17+
raise ValueError("info must be a ProfileInfo object")
18+
19+
first_name_score = 1 if info.first_name else 0
20+
last_name_score = 1 if info.last_name else 0
21+
phone_score = 1 if info.phone else 0
22+
date_birth_score = 1 if info.date_birth else 0
23+
gender_score = 1 if info.gender else 0
24+
summary_score = 1 if info.summary else 0
25+
urls_score = 1 if info.urls else 0
26+
location_score = 1 if info.location else 0
27+
28+
info_score = (
29+
first_name_score
30+
+ last_name_score
31+
+ phone_score
32+
+ date_birth_score
33+
+ gender_score
34+
+ summary_score
35+
+ urls_score
36+
+ location_score
37+
)
38+
info_score = info_score / 8
39+
has_person = info.first_name and info.last_name
40+
41+
return info.email or has_person or info_score >= 0.5
42+
43+
44+
def is_valid_for_searching(
45+
profile: t.Union[t.Dict, HrFlowProfile],
46+
) -> bool:
47+
"""
48+
Check if a profile is valid for searching
49+
50+
Based on the following schemas https://developers.hrflow.ai/docs/profiles-searching
51+
52+
Args:
53+
client: <Hrflow>
54+
Hrflow client
55+
profile: <dict> or <HrFlowProfile>
56+
Profile to check
57+
Return:
58+
<bool> True if the profile is valid for searching,
59+
False otherwise
60+
"""
61+
if isinstance(profile, dict):
62+
profile = HrFlowProfile.parse_obj(profile)
63+
64+
if not isinstance(profile, HrFlowProfile):
65+
raise ValueError("profile must be a dict or a HrFlowProfile object")
66+
67+
return is_valid_info_for_searching(profile.info) and bool(profile.text)

0 commit comments

Comments
 (0)