Spaces:
Running
Running
File size: 5,883 Bytes
edecf53 eb65dfc |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Optional, Dict, List
import pandas as pd
from sentence_transformers import SentenceTransformer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import time
import os
# Set cache directory explicitly (optional, as Dockerfile ENV should handle this)
os.environ["HF_HOME"] = "/app/cache"
os.environ["TRANSFORMERS_CACHE"] = "/app/cache"
app = FastAPI()
# Load datasets (updated path to match Dockerfile)
DATA_DIR = "/app/data/" # Changed from "data/" to "/app/data/"
job_df = pd.read_csv(os.path.join(DATA_DIR, "Updated_Job_Posting_Dataset.csv"), encoding="latin1")
course_df = pd.read_csv(os.path.join(DATA_DIR, "coursera_course_dataset_v2_no_null.csv"))
coding_df = pd.read_csv(os.path.join(DATA_DIR, "Software Questions.csv"), encoding="latin1")
# Preprocess datasets
coding_df.rename(columns={'Question': 'question', 'Answer': 'solutions'}, inplace=True)
job_df.rename(columns={'company_name': 'company', 'required_skills': 'skills'}, inplace=True)
course_df.rename(columns={'Title': 'course_title', 'Skills': 'skills'}, inplace=True)
coding_df.dropna(subset=['question', 'solutions'], inplace=True)
job_df["job_description"] = job_df["job_description"].fillna("")
# Load BERT model and vectorizer
bert_model = SentenceTransformer('paraphrase-MiniLM-L6-v2')
vectorizer = TfidfVectorizer()
# Pydantic model for request body
class UserInput(BaseModel):
name: str
skills: List[str] # Required list of skills
answers: Optional[Dict[str, Dict[str, str]]] = None # Optional answers
# Evaluate coding answers
def evaluate_coding_with_time(user_code, correct_code, start_time):
end_time = time.time()
execution_time = end_time - start_time
vectorized = vectorizer.fit_transform([user_code, correct_code])
similarity = cosine_similarity(vectorized)[0][1] * 100
if execution_time > 120:
similarity -= (execution_time - 120) * 0.1
return round(max(similarity, 0), 2)
# Get coding challenges
def get_coding_challenges(skills, num_questions=5):
skill_challenges = {}
for skill in skills:
relevant = coding_df[coding_df["question"].str.contains(skill, case=False, na=False)]
if not relevant.empty:
skill_challenges[skill] = relevant.sample(min(num_questions, len(relevant)))[["question", "solutions"]].to_dict(orient="records")
else:
skill_challenges[skill] = []
return skill_challenges
# Assign proficiency level
def get_proficiency_level(score):
if score >= 80:
return "Expert"
elif score >= 50:
return "Intermediate"
else:
return "Beginner"
# Recommend courses
def recommend_courses(weak_skills):
if not weak_skills:
return []
courses = course_df[course_df['skills'].str.contains('|'.join(weak_skills), case=False, na=False)]
return courses[['course_title', 'Organization']].head(5).to_dict(orient="records")
# Recommend jobs
def recommend_jobs(skills):
if not skills:
return []
job_df["job_embeddings"] = job_df["job_description"].apply(lambda x: bert_model.encode(str(x)))
user_embedding = bert_model.encode(" ".join(skills))
job_df["BERT_Similarity"] = job_df["job_embeddings"].apply(lambda x: cosine_similarity([x], [user_embedding])[0][0])
top_jobs = job_df.sort_values(by="BERT_Similarity", ascending=False).head(5)
return top_jobs[["job_title", "company", "location", "BERT_Similarity"]].to_dict(orient="records")
@app.get("/")
def read_root():
return {"message": "Skill Assessment API"}
@app.post("/assess")
def assess_skills(user_input: UserInput):
# Extract user data from request
user_name = user_input.name
user_skills = user_input.skills
if not user_skills:
raise HTTPException(status_code=400, detail="Skills list cannot be empty")
# Fetch coding challenges based on provided skills
challenges = get_coding_challenges(user_skills)
# Evaluate skills
user_scores = {}
for skill, challenge_list in challenges.items():
if not challenge_list:
user_scores[skill] = 0
continue
total_score = 0
num_questions = len(challenge_list)
if user_input.answers and skill in user_input.answers:
# Use provided answers
for challenge in challenge_list:
question = challenge["question"]
if question in user_input.answers[skill]:
start_time = time.time() - 10 # Simulate execution time
user_code = user_input.answers[skill][question]
correct_code = challenge["solutions"]
score = evaluate_coding_with_time(user_code, correct_code, start_time)
total_score += score
else:
total_score += 0 # No answer provided for this question
else:
# No answers provided; assign default score (50% per question)
total_score = 50 * num_questions
user_scores[skill] = round(total_score / num_questions, 2)
# Proficiency levels
proficiency_levels = {skill: get_proficiency_level(score) for skill, score in user_scores.items()}
weak_skills = [skill for skill, level in proficiency_levels.items() if level in ["Beginner", "Intermediate"]]
# Recommendations
courses = recommend_courses(weak_skills)
jobs = recommend_jobs(user_skills)
return {
"name": user_name,
"skills": user_skills,
"scores": user_scores,
"proficiency_levels": proficiency_levels,
"recommended_courses": courses,
"recommended_jobs": jobs
}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=7860) |