Spaces:
Sleeping
Sleeping
Update main.py
Browse files
main.py
CHANGED
|
@@ -59,15 +59,21 @@ def extract_json_from_response(response_text):
|
|
| 59 |
logging.error(f"Unexpected error extracting JSON: {str(e)}")
|
| 60 |
raise
|
| 61 |
|
| 62 |
-
def process_with_gemini(model, prompt, text):
|
| 63 |
"""Send combined text (job description and applicant documents) to Gemini and return structured JSON response."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 64 |
full_prompt = f"""
|
| 65 |
You are an expert HR recruiter. Based on the job description and the applicant's documents provided below, assess the applicant's suitability for the job.
|
|
|
|
| 66 |
Job Description:
|
| 67 |
{prompt}
|
| 68 |
|
| 69 |
-
|
| 70 |
-
{text}
|
| 71 |
|
| 72 |
Provide a detailed analysis that includes:
|
| 73 |
- A score out of 100 evaluating the applicant's fit for the role.
|
|
@@ -96,6 +102,7 @@ def process_application():
|
|
| 96 |
- job_id: form data string
|
| 97 |
- job_description: form data string
|
| 98 |
- applicant_id: form data string
|
|
|
|
| 99 |
- files: one or more PDF files (e.g., CV, cover letter)
|
| 100 |
Returns a JSON response with score, recommendation, and justification.
|
| 101 |
"""
|
|
@@ -104,6 +111,7 @@ def process_application():
|
|
| 104 |
job_id = request.form.get('job_id')
|
| 105 |
job_description = request.form.get('job_description')
|
| 106 |
applicant_id = request.form.get('applicant_id')
|
|
|
|
| 107 |
|
| 108 |
if not job_id or not job_description or not applicant_id:
|
| 109 |
return jsonify({'error': 'job_id, job_description, and applicant_id are required'}), 400
|
|
@@ -132,15 +140,34 @@ def process_application():
|
|
| 132 |
# Extract text and combine
|
| 133 |
combined_text += read_pdf(temp_file.name) + "\n\n"
|
| 134 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 135 |
# Configure Gemini and process combined text
|
| 136 |
model = configure_gemini(api_key)
|
| 137 |
-
extracted_data = process_with_gemini(model, job_description, combined_text)
|
| 138 |
|
| 139 |
# Clean up temporary files
|
| 140 |
for temp_file in temp_files:
|
| 141 |
os.remove(temp_file)
|
| 142 |
|
| 143 |
-
#
|
| 144 |
logging.info(f"Processed application for applicant_id: {applicant_id} for job_id: {job_id}")
|
| 145 |
|
| 146 |
return jsonify(extracted_data)
|
|
|
|
| 59 |
logging.error(f"Unexpected error extracting JSON: {str(e)}")
|
| 60 |
raise
|
| 61 |
|
| 62 |
+
def process_with_gemini(model, prompt, text, answers_text=None):
|
| 63 |
"""Send combined text (job description and applicant documents) to Gemini and return structured JSON response."""
|
| 64 |
+
|
| 65 |
+
# Build the applicant section with answers if provided
|
| 66 |
+
applicant_section = f"Applicant Documents:\n{text}"
|
| 67 |
+
if answers_text:
|
| 68 |
+
applicant_section += f"\n\nApplicant's Answers to Screening Questions:\n{answers_text}"
|
| 69 |
+
|
| 70 |
full_prompt = f"""
|
| 71 |
You are an expert HR recruiter. Based on the job description and the applicant's documents provided below, assess the applicant's suitability for the job.
|
| 72 |
+
|
| 73 |
Job Description:
|
| 74 |
{prompt}
|
| 75 |
|
| 76 |
+
{applicant_section}
|
|
|
|
| 77 |
|
| 78 |
Provide a detailed analysis that includes:
|
| 79 |
- A score out of 100 evaluating the applicant's fit for the role.
|
|
|
|
| 102 |
- job_id: form data string
|
| 103 |
- job_description: form data string
|
| 104 |
- applicant_id: form data string
|
| 105 |
+
- questions_answers: (optional) form data string - JSON string containing Q&A pairs
|
| 106 |
- files: one or more PDF files (e.g., CV, cover letter)
|
| 107 |
Returns a JSON response with score, recommendation, and justification.
|
| 108 |
"""
|
|
|
|
| 111 |
job_id = request.form.get('job_id')
|
| 112 |
job_description = request.form.get('job_description')
|
| 113 |
applicant_id = request.form.get('applicant_id')
|
| 114 |
+
questions_answers = request.form.get('questions_answers') # New field for Q&A
|
| 115 |
|
| 116 |
if not job_id or not job_description or not applicant_id:
|
| 117 |
return jsonify({'error': 'job_id, job_description, and applicant_id are required'}), 400
|
|
|
|
| 140 |
# Extract text and combine
|
| 141 |
combined_text += read_pdf(temp_file.name) + "\n\n"
|
| 142 |
|
| 143 |
+
# Parse and format questions_answers if provided
|
| 144 |
+
answers_text = None
|
| 145 |
+
if questions_answers:
|
| 146 |
+
try:
|
| 147 |
+
qa_data = json.loads(questions_answers)
|
| 148 |
+
# Format the Q&A data for better readability
|
| 149 |
+
formatted_answers = []
|
| 150 |
+
if isinstance(qa_data, list):
|
| 151 |
+
for idx, qa in enumerate(qa_data, 1):
|
| 152 |
+
question = qa.get('question', 'N/A')
|
| 153 |
+
response = qa.get('response', 'N/A')
|
| 154 |
+
formatted_answers.append(f"Q{idx}: {question}\nA{idx}: {response}")
|
| 155 |
+
else:
|
| 156 |
+
formatted_answers.append(str(qa_data))
|
| 157 |
+
answers_text = "\n\n".join(formatted_answers)
|
| 158 |
+
except json.JSONDecodeError:
|
| 159 |
+
logging.warning("questions_answers is not valid JSON, treating as plain text")
|
| 160 |
+
answers_text = questions_answers
|
| 161 |
+
|
| 162 |
# Configure Gemini and process combined text
|
| 163 |
model = configure_gemini(api_key)
|
| 164 |
+
extracted_data = process_with_gemini(model, job_description, combined_text, answers_text)
|
| 165 |
|
| 166 |
# Clean up temporary files
|
| 167 |
for temp_file in temp_files:
|
| 168 |
os.remove(temp_file)
|
| 169 |
|
| 170 |
+
# Log the processing
|
| 171 |
logging.info(f"Processed application for applicant_id: {applicant_id} for job_id: {job_id}")
|
| 172 |
|
| 173 |
return jsonify(extracted_data)
|