Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -110,31 +110,33 @@ def search_matching_cvs(jd_text, jd_file, num_results):
|
|
| 110 |
# Format results
|
| 111 |
jd_preview = job_description[:150] + "..." if len(job_description) > 150 else job_description
|
| 112 |
|
| 113 |
-
output = f"""#
|
|
|
|
| 114 |
**Job Description**: {jd_preview}
|
| 115 |
**Search Results**:
|
|
|
|
| 116 |
"""
|
| 117 |
|
| 118 |
for i, cv in enumerate(results, 1):
|
| 119 |
similarity_percentage = cv['weighted_score'] * 100
|
| 120 |
|
| 121 |
-
# Determine match quality and
|
| 122 |
if similarity_percentage >= 80:
|
| 123 |
match_quality = "π’ Excellent Match"
|
| 124 |
-
|
| 125 |
elif similarity_percentage >= 65:
|
| 126 |
match_quality = "π‘ Good Match"
|
| 127 |
-
|
| 128 |
elif similarity_percentage >= 50:
|
| 129 |
match_quality = "π Fair Match"
|
| 130 |
-
|
| 131 |
else:
|
| 132 |
match_quality = "π΄ Weak Match"
|
| 133 |
-
|
| 134 |
|
| 135 |
output += f"""
|
| 136 |
### {i}. **{cv['filename']}**
|
| 137 |
-
<div
|
| 138 |
**{match_quality}** - **{similarity_percentage:.1f}% Overall Match**
|
| 139 |
π **Detailed Scores:**
|
| 140 |
- Best Section Match: {cv['max_similarity']*100:.1f}%
|
|
@@ -144,7 +146,7 @@ def search_matching_cvs(jd_text, jd_file, num_results):
|
|
| 144 |
*"{cv['best_match_text']}"*
|
| 145 |
</div>
|
| 146 |
---
|
| 147 |
-
|
| 148 |
|
| 149 |
return output
|
| 150 |
|
|
@@ -159,6 +161,7 @@ def get_system_status():
|
|
| 159 |
|
| 160 |
if cv_search is None:
|
| 161 |
return f"""
|
|
|
|
| 162 |
## β οΈ System Status: Not Ready
|
| 163 |
|
| 164 |
{initialization_status}
|
|
@@ -168,12 +171,14 @@ def get_system_status():
|
|
| 168 |
- Incorrect folder ID
|
| 169 |
- Folder is not public
|
| 170 |
- No PDF files in the folder
|
|
|
|
| 171 |
"""
|
| 172 |
|
| 173 |
db_info = cv_search.get_database_info()
|
| 174 |
|
| 175 |
if db_info['unique_cvs'] == 0:
|
| 176 |
return f"""
|
|
|
|
| 177 |
## β οΈ System Status: No CVs Loaded
|
| 178 |
|
| 179 |
{initialization_status}
|
|
@@ -182,9 +187,11 @@ def get_system_status():
|
|
| 182 |
- Google Drive folder contains PDF files
|
| 183 |
- Folder is publicly accessible
|
| 184 |
- API key has proper permissions
|
|
|
|
| 185 |
"""
|
| 186 |
|
| 187 |
return f"""
|
|
|
|
| 188 |
## β
System Status: Ready for Search
|
| 189 |
|
| 190 |
π **Database Statistics:**
|
|
@@ -195,6 +202,7 @@ def get_system_status():
|
|
| 195 |
π€ **AI Model**: Sentence Transformers (all-MiniLM-L6-v2)
|
| 196 |
|
| 197 |
π **Sample CVs**: {', '.join(db_info['cv_filenames'][:3])}{'...' if len(db_info['cv_filenames']) > 3 else ''}
|
|
|
|
| 198 |
"""
|
| 199 |
|
| 200 |
# Create Gradio interface
|
|
@@ -212,32 +220,16 @@ def create_interface():
|
|
| 212 |
background: #f8f9fa; padding: 25px; border-radius: 15px; margin: 20px 0;
|
| 213 |
border-left: 5px solid #007bff;
|
| 214 |
}
|
| 215 |
-
.gradio-container .results-container {
|
| 216 |
-
background: #ffffff; padding: 25px; border-radius: 15px;
|
| 217 |
-
border: 1px solid #dee2e6; margin: 20px 0;
|
| 218 |
-
}
|
| 219 |
.gradio-container .header {
|
| 220 |
text-align: center; padding: 30px; background: #74b9ff;
|
| 221 |
color: white; margin: -20px -20px 20px -20px; border-radius: 15px 15px 0 0;
|
| 222 |
}
|
| 223 |
.gradio-container .tab-content { padding: 15px; }
|
| 224 |
-
.gradio-container .excellent-match {
|
| 225 |
-
background: #28a74522; padding: 15px; border-radius: 8px; border-left: 4px solid #28a745;
|
| 226 |
-
}
|
| 227 |
-
.gradio-container .good-match {
|
| 228 |
-
background: #ffc10722; padding: 15px; border-radius: 8px; border-left: 4px solid #ffc107;
|
| 229 |
-
}
|
| 230 |
-
.gradio-container .fair-match {
|
| 231 |
-
background: #fd7e1422; padding: 15px; border-radius: 8px; border-left: 4px solid #fd7e14;
|
| 232 |
-
}
|
| 233 |
-
.gradio-container .weak-match {
|
| 234 |
-
background: #dc354522; padding: 15px; border-radius: 8px; border-left: 4px solid #dc3545;
|
| 235 |
-
}
|
| 236 |
"""
|
| 237 |
|
| 238 |
with gr.Blocks(
|
| 239 |
title="CV Semantic Search - Auto-loaded from Google Drive",
|
| 240 |
-
theme=gr.themes.Default(),
|
| 241 |
css=css
|
| 242 |
) as demo:
|
| 243 |
|
|
@@ -316,6 +308,7 @@ Responsibilities:
|
|
| 316 |
with gr.Group(elem_classes=["results-container"]):
|
| 317 |
search_output = gr.Markdown(
|
| 318 |
"""
|
|
|
|
| 319 |
## π How to Use This System:
|
| 320 |
|
| 321 |
1. **Enter Job Requirements**: Use the text box or upload a PDF with your job description
|
|
@@ -329,8 +322,8 @@ Responsibilities:
|
|
| 329 |
- **Detailed Analysis**: Shows why each CV matches your requirements
|
| 330 |
|
| 331 |
*Enter a job description above to get started!*
|
| 332 |
-
|
| 333 |
-
|
| 334 |
)
|
| 335 |
|
| 336 |
# Refresh Status Button
|
|
|
|
| 110 |
# Format results
|
| 111 |
jd_preview = job_description[:150] + "..." if len(job_description) > 150 else job_description
|
| 112 |
|
| 113 |
+
output = f"""<div style="background: #ffffff; padding: 20px; border-radius: 10px; border: 1px solid #dee2e6;">
|
| 114 |
+
## π― Top {len(results)} Matching CVs
|
| 115 |
**Job Description**: {jd_preview}
|
| 116 |
**Search Results**:
|
| 117 |
+
</div>
|
| 118 |
"""
|
| 119 |
|
| 120 |
for i, cv in enumerate(results, 1):
|
| 121 |
similarity_percentage = cv['weighted_score'] * 100
|
| 122 |
|
| 123 |
+
# Determine match quality and inline styles
|
| 124 |
if similarity_percentage >= 80:
|
| 125 |
match_quality = "π’ Excellent Match"
|
| 126 |
+
quality_style = "background: #28a74522; border-left: 4px solid #28a745;"
|
| 127 |
elif similarity_percentage >= 65:
|
| 128 |
match_quality = "π‘ Good Match"
|
| 129 |
+
quality_style = "background: #ffc10722; border-left: 4px solid #ffc107;"
|
| 130 |
elif similarity_percentage >= 50:
|
| 131 |
match_quality = "π Fair Match"
|
| 132 |
+
quality_style = "background: #fd7e1422; border-left: 4px solid #fd7e14;"
|
| 133 |
else:
|
| 134 |
match_quality = "π΄ Weak Match"
|
| 135 |
+
quality_style = "background: #dc354522; border-left: 4px solid #dc3545;"
|
| 136 |
|
| 137 |
output += f"""
|
| 138 |
### {i}. **{cv['filename']}**
|
| 139 |
+
<div style="{quality_style} padding: 15px; border-radius: 8px; margin: 10px 0;">
|
| 140 |
**{match_quality}** - **{similarity_percentage:.1f}% Overall Match**
|
| 141 |
π **Detailed Scores:**
|
| 142 |
- Best Section Match: {cv['max_similarity']*100:.1f}%
|
|
|
|
| 146 |
*"{cv['best_match_text']}"*
|
| 147 |
</div>
|
| 148 |
---
|
| 149 |
+
"""
|
| 150 |
|
| 151 |
return output
|
| 152 |
|
|
|
|
| 161 |
|
| 162 |
if cv_search is None:
|
| 163 |
return f"""
|
| 164 |
+
<div style="background: #f8f9fa; padding: 20px; border-radius: 10px; border-left: 5px solid #dc3545;">
|
| 165 |
## β οΈ System Status: Not Ready
|
| 166 |
|
| 167 |
{initialization_status}
|
|
|
|
| 171 |
- Incorrect folder ID
|
| 172 |
- Folder is not public
|
| 173 |
- No PDF files in the folder
|
| 174 |
+
</div>
|
| 175 |
"""
|
| 176 |
|
| 177 |
db_info = cv_search.get_database_info()
|
| 178 |
|
| 179 |
if db_info['unique_cvs'] == 0:
|
| 180 |
return f"""
|
| 181 |
+
<div style="background: #f8f9fa; padding: 20px; border-radius: 10px; border-left: 5px solid #dc3545;">
|
| 182 |
## β οΈ System Status: No CVs Loaded
|
| 183 |
|
| 184 |
{initialization_status}
|
|
|
|
| 187 |
- Google Drive folder contains PDF files
|
| 188 |
- Folder is publicly accessible
|
| 189 |
- API key has proper permissions
|
| 190 |
+
</div>
|
| 191 |
"""
|
| 192 |
|
| 193 |
return f"""
|
| 194 |
+
<div style="background: #f8f9fa; padding: 20px; border-radius: 10px; border-left: 5px solid #28a745;">
|
| 195 |
## β
System Status: Ready for Search
|
| 196 |
|
| 197 |
π **Database Statistics:**
|
|
|
|
| 202 |
π€ **AI Model**: Sentence Transformers (all-MiniLM-L6-v2)
|
| 203 |
|
| 204 |
π **Sample CVs**: {', '.join(db_info['cv_filenames'][:3])}{'...' if len(db_info['cv_filenames']) > 3 else ''}
|
| 205 |
+
</div>
|
| 206 |
"""
|
| 207 |
|
| 208 |
# Create Gradio interface
|
|
|
|
| 220 |
background: #f8f9fa; padding: 25px; border-radius: 15px; margin: 20px 0;
|
| 221 |
border-left: 5px solid #007bff;
|
| 222 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 223 |
.gradio-container .header {
|
| 224 |
text-align: center; padding: 30px; background: #74b9ff;
|
| 225 |
color: white; margin: -20px -20px 20px -20px; border-radius: 15px 15px 0 0;
|
| 226 |
}
|
| 227 |
.gradio-container .tab-content { padding: 15px; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 228 |
"""
|
| 229 |
|
| 230 |
with gr.Blocks(
|
| 231 |
title="CV Semantic Search - Auto-loaded from Google Drive",
|
| 232 |
+
theme=gr.themes.Default(),
|
| 233 |
css=css
|
| 234 |
) as demo:
|
| 235 |
|
|
|
|
| 308 |
with gr.Group(elem_classes=["results-container"]):
|
| 309 |
search_output = gr.Markdown(
|
| 310 |
"""
|
| 311 |
+
<div style="background: #ffffff; padding: 25px; border-radius: 15px; border: 1px solid #dee2e6;">
|
| 312 |
## π How to Use This System:
|
| 313 |
|
| 314 |
1. **Enter Job Requirements**: Use the text box or upload a PDF with your job description
|
|
|
|
| 322 |
- **Detailed Analysis**: Shows why each CV matches your requirements
|
| 323 |
|
| 324 |
*Enter a job description above to get started!*
|
| 325 |
+
</div>
|
| 326 |
+
"""
|
| 327 |
)
|
| 328 |
|
| 329 |
# Refresh Status Button
|