Spaces:
Sleeping
Sleeping
Upload 7 files
Browse files- app.py +34 -0
- database.py +20 -0
- job_descriptions.json +15 -0
- requirements.txt +4 -0
- resume_parser.py +19 -0
- skill_matcher.py +20 -0
- tracker.py +7 -0
app.py
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
from chatbot.assistant import chat_with_hf_bot
|
3 |
+
from parser.resume_parser import extract_text_from_pdf
|
4 |
+
from matcher.skill_matcher import match_skills
|
5 |
+
from analytics.tracker import log_question
|
6 |
+
from db.database import init_db, save_chat
|
7 |
+
|
8 |
+
st.set_page_config(page_title="AI Career Coach", layout="wide")
|
9 |
+
init_db()
|
10 |
+
|
11 |
+
st.title("π AI Career Coach")
|
12 |
+
st.subheader("Chatbot + Resume Analysis + Weekly Guidance")
|
13 |
+
|
14 |
+
tab1, tab2 = st.tabs(["π¬ Chatbot", "π Resume Matcher"])
|
15 |
+
|
16 |
+
with tab1:
|
17 |
+
user_input = st.text_input("Ask career-related questions:")
|
18 |
+
if user_input:
|
19 |
+
response = chat_with_hf_bot(user_input)
|
20 |
+
save_chat(user_input, response)
|
21 |
+
log_question(user_input)
|
22 |
+
st.success(response)
|
23 |
+
|
24 |
+
with tab2:
|
25 |
+
uploaded_file = st.file_uploader("Upload your Resume (PDF only)", type="pdf")
|
26 |
+
if uploaded_file:
|
27 |
+
resume_text = extract_text_from_pdf(uploaded_file)
|
28 |
+
st.markdown("**Extracted Skills from Resume:**")
|
29 |
+
st.write(resume_text)
|
30 |
+
|
31 |
+
matched_roles = match_skills(resume_text)
|
32 |
+
st.markdown("**Suggested Roles based on Resume:**")
|
33 |
+
for role in matched_roles:
|
34 |
+
st.write(f"β
{role}")
|
database.py
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import sqlite3
|
2 |
+
|
3 |
+
def init_db():
|
4 |
+
conn = sqlite3.connect("db/careercoach.db")
|
5 |
+
c = conn.cursor()
|
6 |
+
c.execute('''CREATE TABLE IF NOT EXISTS chats (
|
7 |
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
8 |
+
question TEXT,
|
9 |
+
answer TEXT,
|
10 |
+
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
|
11 |
+
)''')
|
12 |
+
conn.commit()
|
13 |
+
conn.close()
|
14 |
+
|
15 |
+
def save_chat(question, answer):
|
16 |
+
conn = sqlite3.connect("db/careercoach.db")
|
17 |
+
c = conn.cursor()
|
18 |
+
c.execute("INSERT INTO chats (question, answer) VALUES (?, ?)", (question, answer))
|
19 |
+
conn.commit()
|
20 |
+
conn.close()
|
job_descriptions.json
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
[
|
2 |
+
{
|
3 |
+
"role": "Data Scientist",
|
4 |
+
"description": "Proficient in Python, SQL, machine learning, data visualization, and statistical modeling."
|
5 |
+
},
|
6 |
+
{
|
7 |
+
"role": "Frontend Developer",
|
8 |
+
"description": "Skilled in HTML, CSS, JavaScript, React, and responsive web design."
|
9 |
+
},
|
10 |
+
{
|
11 |
+
"role": "AI Engineer",
|
12 |
+
"description": "Experience with deep learning, NLP, PyTorch, TensorFlow, and deploying ML models."
|
13 |
+
}
|
14 |
+
]
|
15 |
+
|
requirements.txt
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
streamlit
|
2 |
+
requests
|
3 |
+
pymupdf
|
4 |
+
sqlite3
|
resume_parser.py
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import PyPDF2
|
2 |
+
import re
|
3 |
+
|
4 |
+
def extract_text_from_pdf(pdf_file):
|
5 |
+
text = ""
|
6 |
+
reader = PyPDF2.PdfReader(pdf_file)
|
7 |
+
for page in reader.pages:
|
8 |
+
text += page.extract_text()
|
9 |
+
return text
|
10 |
+
|
11 |
+
def clean_text(text):
|
12 |
+
text = re.sub(r'\s+', ' ', text)
|
13 |
+
text = text.strip()
|
14 |
+
return text
|
15 |
+
|
16 |
+
def parse_resume(pdf_file):
|
17 |
+
raw_text = extract_text_from_pdf(pdf_file)
|
18 |
+
cleaned_text = clean_text(raw_text)
|
19 |
+
return cleaned_text
|
skill_matcher.py
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from sklearn.feature_extraction.text import TfidfVectorizer
|
2 |
+
from sklearn.metrics.pairwise import cosine_similarity
|
3 |
+
import json
|
4 |
+
|
5 |
+
def load_job_descriptions(path='data/job_descriptions.json'):
|
6 |
+
with open(path, 'r') as f:
|
7 |
+
jobs = json.load(f)
|
8 |
+
return jobs
|
9 |
+
|
10 |
+
def compare_with_jobs(resume_text, job_descriptions):
|
11 |
+
results = []
|
12 |
+
vectorizer = TfidfVectorizer().fit_transform([resume_text] + [job["description"] for job in job_descriptions])
|
13 |
+
vectors = vectorizer.toarray()
|
14 |
+
|
15 |
+
resume_vector = vectors[0]
|
16 |
+
for idx, job in enumerate(job_descriptions):
|
17 |
+
job_vector = vectors[idx + 1]
|
18 |
+
similarity = cosine_similarity([resume_vector], [job_vector])[0][0]
|
19 |
+
results.append({"role": job["role"], "match": round(similarity * 100, 2)})
|
20 |
+
return sorted(results, key=lambda x: x["match"], reverse=True)
|
tracker.py
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import json
|
2 |
+
from datetime import datetime
|
3 |
+
|
4 |
+
def log_question(question):
|
5 |
+
log_entry = {"question": question, "timestamp": str(datetime.now())}
|
6 |
+
with open("data/weekly_tracker.json", "a") as f:
|
7 |
+
f.write(json.dumps(log_entry) + "\n")
|