Spaces:
Build error
Build error
Upload 5 files
Browse files- app.py +1 -0
- utils/parser.py +26 -0
- utils/scorer.py +12 -0
- utils/suggestions.py +38 -0
- utils/visualizer.py +14 -0
app.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
REPLACE_WITH_FINAL_APP_CODE
|
utils/parser.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
import fitz # PyMuPDF
|
| 3 |
+
import spacy
|
| 4 |
+
|
| 5 |
+
nlp = spacy.load("en_core_web_sm")
|
| 6 |
+
|
| 7 |
+
def parse_cv(file_path):
|
| 8 |
+
text = ""
|
| 9 |
+
with fitz.open(file_path) as doc:
|
| 10 |
+
for page in doc:
|
| 11 |
+
text += page.get_text()
|
| 12 |
+
|
| 13 |
+
doc_nlp = nlp(text)
|
| 14 |
+
education_level = "Unknown"
|
| 15 |
+
if "bachelor" in text.lower():
|
| 16 |
+
education_level = "Bachelor's Degree"
|
| 17 |
+
elif "master" in text.lower():
|
| 18 |
+
education_level = "Master's Degree"
|
| 19 |
+
elif "phd" in text.lower() or "doctor" in text.lower():
|
| 20 |
+
education_level = "PhD or Doctorate"
|
| 21 |
+
elif "high school" in text.lower():
|
| 22 |
+
education_level = "High School"
|
| 23 |
+
|
| 24 |
+
cv_type = "Technical" if any(tok.text.lower() in ["engineer", "developer", "python", "data"] for tok in doc_nlp) else "Non-Technical"
|
| 25 |
+
|
| 26 |
+
return text, education_level, cv_type
|
utils/scorer.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
def get_cv_score(text):
|
| 3 |
+
score = 50
|
| 4 |
+
if "python" in text.lower():
|
| 5 |
+
score += 10
|
| 6 |
+
if "project" in text.lower():
|
| 7 |
+
score += 10
|
| 8 |
+
if "lead" in text.lower() or "manager" in text.lower():
|
| 9 |
+
score += 10
|
| 10 |
+
if "certified" in text.lower() or "certification" in text.lower():
|
| 11 |
+
score += 10
|
| 12 |
+
return min(score, 100)
|
utils/suggestions.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
import requests
|
| 3 |
+
import os
|
| 4 |
+
|
| 5 |
+
HF_API_TOKEN = os.getenv("HF_API_TOKEN")
|
| 6 |
+
ADZUNA_APP_ID = os.getenv("ADZUNA_APP_ID")
|
| 7 |
+
ADZUNA_API_KEY = os.getenv("ADZUNA_API_KEY")
|
| 8 |
+
|
| 9 |
+
def call_llm(prompt):
|
| 10 |
+
headers = {"Authorization": f"Bearer {HF_API_TOKEN}"}
|
| 11 |
+
json_data = {
|
| 12 |
+
"inputs": prompt,
|
| 13 |
+
"parameters": {"max_new_tokens": 300},
|
| 14 |
+
}
|
| 15 |
+
response = requests.post("https://api-inference.huggingface.co/models/mistralai/Mistral-7B-Instruct-v0.1", headers=headers, json=json_data)
|
| 16 |
+
if response.status_code == 200:
|
| 17 |
+
return response.json()[0]["generated_text"]
|
| 18 |
+
raise Exception(f"Hugging Face API Error {response.status_code}: {response.text}")
|
| 19 |
+
|
| 20 |
+
def get_certification_suggestions(text):
|
| 21 |
+
return call_llm(f"Suggest professional certifications based on this CV: {text}")
|
| 22 |
+
|
| 23 |
+
def get_higher_education_suggestions(text):
|
| 24 |
+
return call_llm(f"Suggest higher education programs based on this CV: {text}")
|
| 25 |
+
|
| 26 |
+
def get_visa_recommendations(text):
|
| 27 |
+
return call_llm(f"Suggest visa opportunities in top countries based on this CV: {text}")
|
| 28 |
+
|
| 29 |
+
def get_career_advice(text):
|
| 30 |
+
return call_llm(f"Act like a career counselor. Give personalized advice for this CV: {text}")
|
| 31 |
+
|
| 32 |
+
def get_job_listings(text):
|
| 33 |
+
url = "https://api.adzuna.com/v1/api/jobs/us/search/1"
|
| 34 |
+
params = {"app_id": ADZUNA_APP_ID, "app_key": ADZUNA_API_KEY, "what": "engineer", "results_per_page": 5}
|
| 35 |
+
response = requests.get(url, params=params)
|
| 36 |
+
if response.status_code == 200:
|
| 37 |
+
return [f"{job['title']} - {job['location']['display_name']}" for job in response.json().get("results", [])]
|
| 38 |
+
return ["No jobs found"]
|
utils/visualizer.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
import matplotlib.pyplot as plt
|
| 3 |
+
|
| 4 |
+
def generate_timeline(text):
|
| 5 |
+
stages = ["Skill Development", "Certifications", "Higher Education", "Job Applications", "Visa Process"]
|
| 6 |
+
durations = [2, 2, 3, 1, 1]
|
| 7 |
+
fig, ax = plt.subplots(figsize=(10, 2))
|
| 8 |
+
ax.barh(["Roadmap"], [sum(durations)], color="lightgray")
|
| 9 |
+
left = 0
|
| 10 |
+
for stage, duration in zip(stages, durations):
|
| 11 |
+
ax.barh(["Roadmap"], [duration], left=left, label=stage)
|
| 12 |
+
left += duration
|
| 13 |
+
ax.legend()
|
| 14 |
+
return fig
|