Spaces:
Running
Running
Commit
·
979bdd1
1
Parent(s):
ee816fa
projects
Browse files- Process/utils.py +69 -3
- ResumeATS/urls.py +2 -1
Process/utils.py
CHANGED
@@ -24,8 +24,9 @@ class ATSResumeParser:
|
|
24 |
def __init__(self):
|
25 |
logger.info("Initializing ATSResumeParser")
|
26 |
self.score_weights = {
|
27 |
-
"skills_match":
|
28 |
-
"experience_relevance":
|
|
|
29 |
"education_relevance": 10,
|
30 |
"overall_formatting": 15,
|
31 |
"keyword_optimization": 10,
|
@@ -92,6 +93,67 @@ class ATSResumeParser:
|
|
92 |
"explanation": response["explanation"],
|
93 |
}
|
94 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
95 |
def _score_experience(
|
96 |
self, experience: List[Dict], job_description: Optional[str]
|
97 |
) -> Dict:
|
@@ -252,7 +314,6 @@ class ATSResumeParser:
|
|
252 |
detailed_feedback = {}
|
253 |
|
254 |
with concurrent.futures.ThreadPoolExecutor() as executor:
|
255 |
-
# Define tasks to run in parallel
|
256 |
tasks = {
|
257 |
"skills_match": executor.submit(
|
258 |
self._score_skills,
|
@@ -264,6 +325,11 @@ class ATSResumeParser:
|
|
264 |
structured_data.get("experience", []),
|
265 |
job_description,
|
266 |
),
|
|
|
|
|
|
|
|
|
|
|
267 |
"education_relevance": executor.submit(
|
268 |
self._score_education, structured_data.get("education", [])
|
269 |
),
|
|
|
24 |
def __init__(self):
|
25 |
logger.info("Initializing ATSResumeParser")
|
26 |
self.score_weights = {
|
27 |
+
"skills_match": 20,
|
28 |
+
"experience_relevance": 20,
|
29 |
+
"project_relevance": 15,
|
30 |
"education_relevance": 10,
|
31 |
"overall_formatting": 15,
|
32 |
"keyword_optimization": 10,
|
|
|
93 |
"explanation": response["explanation"],
|
94 |
}
|
95 |
|
96 |
+
def _score_projects(
|
97 |
+
self, projects: List[Dict], job_description: Optional[str]
|
98 |
+
) -> Dict:
|
99 |
+
"""Score projects with optimized processing"""
|
100 |
+
print("567898765", projects)
|
101 |
+
if not projects:
|
102 |
+
return {
|
103 |
+
"score": 0,
|
104 |
+
"matching": [],
|
105 |
+
"missing": [],
|
106 |
+
"explanation": "No projects provided",
|
107 |
+
}
|
108 |
+
|
109 |
+
# Basic score based only on project count
|
110 |
+
base_score = 70
|
111 |
+
|
112 |
+
if not job_description:
|
113 |
+
return {
|
114 |
+
"score": base_score,
|
115 |
+
"matching": [p.get("title", "Untitled Project") for p in projects[:3]],
|
116 |
+
"missing": [],
|
117 |
+
"explanation": "No job description provided",
|
118 |
+
}
|
119 |
+
|
120 |
+
# Fix: Use 'name' instead of 'title' to match your data structure
|
121 |
+
simplified_projects = [
|
122 |
+
{"title": p.get("title", ""), "description": p.get("description", "")}
|
123 |
+
for p in projects[:3]
|
124 |
+
]
|
125 |
+
try:
|
126 |
+
prompt = f"""Projects: {json.dumps(simplified_projects)}. Job description: {job_description[:500]}.
|
127 |
+
Analyze how well these projects match the job requirements. In your response:
|
128 |
+
- Give specific matching elements from projects relevant to the job
|
129 |
+
- List missing project types or skills that would improve the match
|
130 |
+
- Keep lists concise with specific items, not paragraphs
|
131 |
+
- Provide a numerical score between 0-10 reflecting the overall match quality"""
|
132 |
+
|
133 |
+
response = self._parse_gemini_response(
|
134 |
+
get_response(prompt, SYSTEM_INSTRUCTION)
|
135 |
+
)
|
136 |
+
|
137 |
+
score = response.get("score", 5.0)
|
138 |
+
|
139 |
+
return {
|
140 |
+
"score": (base_score + (score * 10)) / 2,
|
141 |
+
"matching": response.get("matching", []),
|
142 |
+
"missing": response.get("missing", []),
|
143 |
+
"explanation": response.get(
|
144 |
+
"explanation", "Project assessment completed"
|
145 |
+
),
|
146 |
+
}
|
147 |
+
except Exception as e:
|
148 |
+
logger.error(f"Error in _score_projects: {e}")
|
149 |
+
logger.debug(traceback.format_exc())
|
150 |
+
return {
|
151 |
+
"score": base_score,
|
152 |
+
"matching": [p.get("name", "Untitled Project") for p in projects[:3]],
|
153 |
+
"missing": [],
|
154 |
+
"explanation": "Error analyzing project relevance",
|
155 |
+
}
|
156 |
+
|
157 |
def _score_experience(
|
158 |
self, experience: List[Dict], job_description: Optional[str]
|
159 |
) -> Dict:
|
|
|
314 |
detailed_feedback = {}
|
315 |
|
316 |
with concurrent.futures.ThreadPoolExecutor() as executor:
|
|
|
317 |
tasks = {
|
318 |
"skills_match": executor.submit(
|
319 |
self._score_skills,
|
|
|
325 |
structured_data.get("experience", []),
|
326 |
job_description,
|
327 |
),
|
328 |
+
"project_relevance": executor.submit(
|
329 |
+
self._score_projects,
|
330 |
+
structured_data.get("projects", []),
|
331 |
+
job_description,
|
332 |
+
),
|
333 |
"education_relevance": executor.submit(
|
334 |
self._score_education, structured_data.get("education", [])
|
335 |
),
|
ResumeATS/urls.py
CHANGED
@@ -14,9 +14,10 @@ Including another URLconf
|
|
14 |
1. Import the include() function: from django.urls import include, path
|
15 |
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
16 |
"""
|
|
|
17 |
from django.contrib import admin
|
18 |
from django.urls import path, include
|
19 |
|
20 |
urlpatterns = [
|
21 |
-
path(
|
22 |
]
|
|
|
14 |
1. Import the include() function: from django.urls import include, path
|
15 |
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
16 |
"""
|
17 |
+
|
18 |
from django.contrib import admin
|
19 |
from django.urls import path, include
|
20 |
|
21 |
urlpatterns = [
|
22 |
+
path("", include("Process.urls")),
|
23 |
]
|