Spaces:
Sleeping
Sleeping
Johnny
commited on
Commit
·
cca9b28
1
Parent(s):
2854e2c
updated summarize_resume to pegasus
Browse files
config.py
CHANGED
|
@@ -19,7 +19,7 @@ supabase = create_client(SUPABASE_URL, SUPABASE_KEY)
|
|
| 19 |
embedding_model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
|
| 20 |
|
| 21 |
HF_MODELS = {
|
| 22 |
-
"
|
| 23 |
"gemma": "https://router.huggingface.co/nebius/v1/chat/completions"
|
| 24 |
|
| 25 |
}
|
|
@@ -30,12 +30,12 @@ if not HF_API_TOKEN:
|
|
| 30 |
|
| 31 |
HF_HEADERS = {"Authorization": f"Bearer {HF_API_TOKEN}"}
|
| 32 |
|
| 33 |
-
def query(payload, model="
|
| 34 |
"""
|
| 35 |
Sends a request to the Hugging Face API with retries and better error handling.
|
| 36 |
"""
|
| 37 |
if model not in HF_MODELS:
|
| 38 |
-
raise ValueError(f"Invalid model name: {model}. Choose '
|
| 39 |
|
| 40 |
api_url = HF_MODELS[model]
|
| 41 |
|
|
|
|
| 19 |
embedding_model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
|
| 20 |
|
| 21 |
HF_MODELS = {
|
| 22 |
+
"pegasus": "https://router.huggingface.co/hf-inference/models/google/pegasus-xsum",
|
| 23 |
"gemma": "https://router.huggingface.co/nebius/v1/chat/completions"
|
| 24 |
|
| 25 |
}
|
|
|
|
| 30 |
|
| 31 |
HF_HEADERS = {"Authorization": f"Bearer {HF_API_TOKEN}"}
|
| 32 |
|
| 33 |
+
def query(payload, model="pegasus", retries=5, delay=5):
|
| 34 |
"""
|
| 35 |
Sends a request to the Hugging Face API with retries and better error handling.
|
| 36 |
"""
|
| 37 |
if model not in HF_MODELS:
|
| 38 |
+
raise ValueError(f"Invalid model name: {model}. Choose 'pegasus' for summarization.")
|
| 39 |
|
| 40 |
api_url = HF_MODELS[model]
|
| 41 |
|
utils.py
CHANGED
|
@@ -163,25 +163,26 @@ def extract_email(resume_text):
|
|
| 163 |
match = re.search(r"[\w\.-]+@[\w\.-]+", resume_text)
|
| 164 |
return match.group(0) if match else None
|
| 165 |
|
| 166 |
-
|
| 167 |
def summarize_resume(resume_text):
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
return "Summary unavailable due to API issues."
|
| 176 |
|
| 177 |
try:
|
| 178 |
-
response =
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
|
|
|
|
|
|
|
|
|
| 182 |
except Exception as e:
|
| 183 |
-
print(f"Error
|
| 184 |
-
return "Summary unavailable."
|
| 185 |
|
| 186 |
|
| 187 |
# === Data Storage & Reporting ===
|
|
@@ -229,17 +230,14 @@ def generate_pdf_report(shortlisted_candidates, questions=None):
|
|
| 229 |
|
| 230 |
|
| 231 |
def generate_interview_questions_from_summaries(candidates):
|
| 232 |
-
"""
|
| 233 |
-
Generates 5 interview questions based on combined summaries using Gemma model.
|
| 234 |
-
"""
|
| 235 |
if not isinstance(candidates, list):
|
| 236 |
raise TypeError("Expected a list of candidate dictionaries.")
|
| 237 |
|
| 238 |
summaries = " ".join(c.get("summary", "") for c in candidates)
|
| 239 |
|
| 240 |
prompt = (
|
| 241 |
-
"Based on the following summary of
|
| 242 |
-
"generate 5 thoughtful, general interview questions that would help a recruiter assess their fit:\n"
|
| 243 |
f"{summaries}"
|
| 244 |
)
|
| 245 |
|
|
@@ -251,10 +249,27 @@ def generate_interview_questions_from_summaries(candidates):
|
|
| 251 |
)
|
| 252 |
result = response.choices[0].message.content
|
| 253 |
|
| 254 |
-
|
| 255 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 256 |
|
| 257 |
return [f"Q{i+1}. {q}" for i, q in enumerate(questions[:5])] or ["⚠️ No questions generated."]
|
|
|
|
| 258 |
except Exception as e:
|
| 259 |
print(f"❌ Error generating interview questions: {e}")
|
| 260 |
return ["⚠️ Error generating questions."]
|
|
|
|
| 163 |
match = re.search(r"[\w\.-]+@[\w\.-]+", resume_text)
|
| 164 |
return match.group(0) if match else None
|
| 165 |
|
|
|
|
| 166 |
def summarize_resume(resume_text):
|
| 167 |
+
prompt = (
|
| 168 |
+
"You are an expert technical recruiter. Extract a professional summary for this candidate based on their resume text. "
|
| 169 |
+
"Include: full name (if found), job title, years of experience, key technologies/tools, industries worked in, and certifications. "
|
| 170 |
+
"Format it as a professional summary paragraph.\n\n"
|
| 171 |
+
f"Resume:\n{resume_text}\n\n"
|
| 172 |
+
"Summary:"
|
| 173 |
+
)
|
|
|
|
| 174 |
|
| 175 |
try:
|
| 176 |
+
response = client.chat_completion(
|
| 177 |
+
messages=[{"role": "user", "content": prompt}],
|
| 178 |
+
temperature=0.5,
|
| 179 |
+
max_tokens=300,
|
| 180 |
+
)
|
| 181 |
+
result = response.choices[0].message.content.strip()
|
| 182 |
+
return result
|
| 183 |
except Exception as e:
|
| 184 |
+
print(f"❌ Error generating structured summary: {e}")
|
| 185 |
+
return "Summary unavailable due to API issues."
|
| 186 |
|
| 187 |
|
| 188 |
# === Data Storage & Reporting ===
|
|
|
|
| 230 |
|
| 231 |
|
| 232 |
def generate_interview_questions_from_summaries(candidates):
|
|
|
|
|
|
|
|
|
|
| 233 |
if not isinstance(candidates, list):
|
| 234 |
raise TypeError("Expected a list of candidate dictionaries.")
|
| 235 |
|
| 236 |
summaries = " ".join(c.get("summary", "") for c in candidates)
|
| 237 |
|
| 238 |
prompt = (
|
| 239 |
+
"Based on the following summary of a top candidate for a job role, "
|
| 240 |
+
"generate 5 thoughtful, general interview questions that would help a recruiter assess their fit:\n\n"
|
| 241 |
f"{summaries}"
|
| 242 |
)
|
| 243 |
|
|
|
|
| 249 |
)
|
| 250 |
result = response.choices[0].message.content
|
| 251 |
|
| 252 |
+
# Clean and normalize questions
|
| 253 |
+
raw_questions = result.split("\n")
|
| 254 |
+
questions = []
|
| 255 |
+
|
| 256 |
+
for q in raw_questions:
|
| 257 |
+
q = q.strip()
|
| 258 |
+
|
| 259 |
+
# Skip empty lines and markdown headers
|
| 260 |
+
if not q or re.match(r"^#+\s*", q):
|
| 261 |
+
continue
|
| 262 |
+
|
| 263 |
+
# Remove leading "Q1.", "1)", etc.
|
| 264 |
+
q = re.sub(r"^(?:Q?\d+[\.\)\-]?\s*)+", "", q)
|
| 265 |
+
|
| 266 |
+
# Remove markdown bold/italics (**, *, etc.)
|
| 267 |
+
q = re.sub(r"[*_]+", "", q)
|
| 268 |
+
|
| 269 |
+
questions.append(q.strip())
|
| 270 |
|
| 271 |
return [f"Q{i+1}. {q}" for i, q in enumerate(questions[:5])] or ["⚠️ No questions generated."]
|
| 272 |
+
|
| 273 |
except Exception as e:
|
| 274 |
print(f"❌ Error generating interview questions: {e}")
|
| 275 |
return ["⚠️ Error generating questions."]
|