Update app.py
Browse files
app.py
CHANGED
@@ -1,94 +1,242 @@
|
|
1 |
-
import threading
|
2 |
-
import time # Simulate a long task for demonstration
|
3 |
-
from transformers import pipeline
|
4 |
-
from datasets import load_dataset
|
5 |
import streamlit as st
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
|
7 |
-
|
8 |
-
|
|
|
9 |
universities_url = "https://www.4icu.org/top-universities-world/"
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
def
|
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 |
-
st.
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
else:
|
53 |
-
st.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
|
55 |
-
#
|
56 |
if "profile_data" in st.session_state:
|
57 |
-
st.
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
if answer:
|
68 |
-
st.
|
69 |
-
|
70 |
-
|
|
|
|
|
|
|
|
|
|
|
71 |
else:
|
72 |
-
st.
|
|
|
|
|
|
|
|
|
73 |
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import streamlit as st
|
2 |
+
import pandas as pd
|
3 |
+
from transformers import pipeline
|
4 |
+
import time
|
5 |
+
|
6 |
+
# Load datasets from CSV files
|
7 |
+
@st.cache_resource
|
8 |
+
def load_csv_datasets():
|
9 |
+
jobs_data = pd.read_csv("job_descriptions.csv")
|
10 |
+
courses_data = pd.read_csv("courses_data.csv")
|
11 |
+
return jobs_data, courses_data
|
12 |
|
13 |
+
jobs_data, courses_data = load_csv_datasets()
|
14 |
+
|
15 |
+
# Constants
|
16 |
universities_url = "https://www.4icu.org/top-universities-world/"
|
17 |
+
|
18 |
+
# Initialize the text generation pipeline
|
19 |
+
@st.cache_resource
|
20 |
+
def load_pipeline():
|
21 |
+
return pipeline("text2text-generation", model="google/flan-t5-large")
|
22 |
+
|
23 |
+
qa_pipeline = load_pipeline()
|
24 |
+
|
25 |
+
# Streamlit App Interface
|
26 |
+
st.markdown(
|
27 |
+
"""
|
28 |
+
<div style="display: flex; align-items: center; gap: 10px; flex-wrap: wrap;">
|
29 |
+
<h1 style="font-size: 29px; display: inline-block; margin-right: 10px;">
|
30 |
+
<img src="https://img.icons8.com/ios-filled/50/000000/graduation-cap.png" width="40" alt="Degree icon"/>
|
31 |
+
Confused about which career to pursue?
|
32 |
+
</h1>
|
33 |
+
<h2 style="font-size: 25px; display: inline-block; margin: 0;">Let CareerCompass help you decide in two simple steps</h2>
|
34 |
+
</div>
|
35 |
+
""",
|
36 |
+
unsafe_allow_html=True,
|
37 |
+
)
|
38 |
+
|
39 |
+
# Display the appropriate subheader based on profile data status
|
40 |
+
if "profile_data" not in st.session_state or not st.session_state.get("profile_data_saved", False):
|
41 |
+
st.markdown("<h3 style='font-size: 20px;'>Step 1: Find out profile questions on the left sidebar and follow the instructions.</h3>", unsafe_allow_html=True)
|
42 |
+
|
43 |
+
# Sidebar for Profile Setup
|
44 |
+
st.sidebar.header("Profile Setup")
|
45 |
+
educational_background = st.sidebar.selectbox("Educational Background", [
|
46 |
+
"Computer Science", "Engineering", "Business Administration", "Life Sciences",
|
47 |
+
"Social Sciences", "Arts and Humanities", "Mathematics", "Physical Sciences",
|
48 |
+
"Law", "Education", "Medical Sciences", "Other"
|
49 |
+
])
|
50 |
+
interests = st.sidebar.text_input("Interests (e.g., AI, Data Science, Engineering)")
|
51 |
+
tech_skills = st.sidebar.text_area("Technical Skills (e.g., Python, SQL, Machine Learning)")
|
52 |
+
soft_skills = st.sidebar.text_area("Soft Skills (e.g., Communication, Teamwork)")
|
53 |
+
|
54 |
+
# Profile validation and saving
|
55 |
+
def are_profile_fields_filled():
|
56 |
+
return all([educational_background, interests.strip(), tech_skills.strip(), soft_skills.strip()])
|
57 |
+
|
58 |
+
if st.sidebar.button("Save Profile"):
|
59 |
+
if are_profile_fields_filled():
|
60 |
+
with st.spinner('Saving your profile...'):
|
61 |
+
time.sleep(2)
|
62 |
+
st.session_state.profile_data = {
|
63 |
+
"educational_background": educational_background,
|
64 |
+
"interests": interests,
|
65 |
+
"tech_skills": tech_skills,
|
66 |
+
"soft_skills": soft_skills
|
67 |
+
}
|
68 |
+
st.session_state.profile_data_saved = True # Set the profile data saved flag
|
69 |
+
st.session_state.question_index = 0 # Initialize question index
|
70 |
+
st.session_state.answers = {} # Initialize dictionary for answers
|
71 |
+
st.session_state.ask_additional_questions = None # Reset question flag
|
72 |
+
st.session_state.show_additional_question_buttons = True # Show buttons after profile save
|
73 |
+
st.sidebar.success("Profile saved successfully!")
|
74 |
+
st.markdown("<h2 style='font-size: 25px;'>Step 2: For more Accurate Analysis, Do you wish to provide more information?</h2>", unsafe_allow_html=True)
|
75 |
else:
|
76 |
+
st.sidebar.error("Please fill in all the fields before saving your profile.")
|
77 |
+
|
78 |
+
# Button actions
|
79 |
+
if "show_additional_question_buttons" in st.session_state:
|
80 |
+
if st.session_state.show_additional_question_buttons:
|
81 |
+
col1, col2 = st.columns(2)
|
82 |
+
with col1:
|
83 |
+
if st.button("Yes, ask me more questions"):
|
84 |
+
st.session_state.ask_additional_questions = True
|
85 |
+
st.session_state.show_additional_question_buttons = False # Hide buttons after click
|
86 |
+
with col2:
|
87 |
+
if st.button("Skip and generate recommendations"):
|
88 |
+
st.session_state.ask_additional_questions = False
|
89 |
+
st.session_state.show_additional_question_buttons = False # Hide buttons after click
|
90 |
+
|
91 |
+
# Additional questions for more tailored recommendations
|
92 |
+
additional_questions = [
|
93 |
+
"What subjects do you enjoy learning about the most, and why?",
|
94 |
+
"What activities or hobbies do you find most engaging and meaningful outside of school?",
|
95 |
+
"Can you describe a perfect day in your dream career? What tasks would you be doing?",
|
96 |
+
"Are you more inclined towards working independently or as part of a team?",
|
97 |
+
"Do you prefer structured schedules or flexibility in your work?",
|
98 |
+
"What values are most important to you in a career (e.g., creativity, stability, helping others)?",
|
99 |
+
"How important is financial stability to you in your future career?",
|
100 |
+
"Are you interested in pursuing a career that involves working with people, technology, or the environment?",
|
101 |
+
"Would you prefer a career with a clear progression path or one with more entrepreneurial freedom?",
|
102 |
+
"What problems or challenges do you want to solve or address through your career?"
|
103 |
+
]
|
104 |
|
105 |
+
# Display dynamic questions or proceed to generating recommendations
|
106 |
if "profile_data" in st.session_state:
|
107 |
+
if st.session_state.get("ask_additional_questions") is True:
|
108 |
+
total_questions = len(additional_questions)
|
109 |
+
if "question_index" not in st.session_state:
|
110 |
+
st.session_state.question_index = 0
|
111 |
+
|
112 |
+
if st.session_state.question_index < total_questions:
|
113 |
+
question_number = st.session_state.question_index + 1
|
114 |
+
question = additional_questions[st.session_state.question_index]
|
115 |
+
|
116 |
+
# Display question number and question text
|
117 |
+
st.markdown(f"""### Question {question_number}:
|
118 |
+
{question}""")
|
119 |
+
|
120 |
+
answer = st.text_input("Your Answer", key=f"q{st.session_state.question_index}")
|
121 |
+
|
122 |
+
# Display progress bar with formatted text showing "current/total"
|
123 |
+
progress = (st.session_state.question_index + 1) / total_questions
|
124 |
+
st.progress(progress)
|
125 |
+
st.write(f"Progress: {question_number}/{total_questions}")
|
126 |
+
|
127 |
+
if st.button("Submit Answer", key=f"submit{st.session_state.question_index}"):
|
128 |
if answer:
|
129 |
+
st.warning("Data saved successfully. click again to proceed")
|
130 |
+
# Save the answer and increment the question index
|
131 |
+
st.session_state.question_index += 1
|
132 |
+
st.session_state.answers[question] = answer
|
133 |
+
|
134 |
+
# No need to call a special function; the app will rerun automatically
|
135 |
+
else:
|
136 |
+
st.warning("Please enter an answer before submitting.")
|
137 |
else:
|
138 |
+
st.success("All questions have been answered. Click below to generate your recommendations.")
|
139 |
+
if st.button("Generate Response"):
|
140 |
+
st.warning("Data saved successfully. click again to proceed")
|
141 |
+
st.session_state.profile_data.update(st.session_state.answers)
|
142 |
+
st.session_state.ask_additional_questions = False
|
143 |
|
144 |
+
elif st.session_state.get("ask_additional_questions") is False:
|
145 |
+
# Directly generate recommendations
|
146 |
+
st.header("Generating Recommendations")
|
147 |
+
with st.spinner('Generating recommendations...'):
|
148 |
+
time.sleep(2) # Simulate processing time
|
149 |
+
|
150 |
+
# Extracting user profile data
|
151 |
+
profile = st.session_state.profile_data
|
152 |
+
user_tech_skills = set(skill.strip().lower() for skill in profile["tech_skills"].split(","))
|
153 |
+
user_soft_skills = set(skill.strip().lower() for skill in profile["soft_skills"].split(","))
|
154 |
+
user_interests = set(interest.strip().lower() for interest in profile["interests"].split(","))
|
155 |
+
user_answers = st.session_state.get('answers', {})
|
156 |
+
|
157 |
+
# Job Recommendations using refined scoring logic
|
158 |
+
def match_job_criteria(row, profile, user_answers):
|
159 |
+
job_title = row['Job Title'].lower()
|
160 |
+
job_description = row['Job Description'].lower()
|
161 |
+
qualifications = row['Qualifications'].lower()
|
162 |
+
skills = row['skills'].lower()
|
163 |
+
role = row['Role'].lower()
|
164 |
+
|
165 |
+
educational_background = profile['educational_background'].lower()
|
166 |
+
tech_skills = set(skill.strip().lower() for skill in profile["tech_skills"].split(","))
|
167 |
+
soft_skills = set(skill.strip().lower() for skill in profile["soft_skills"].split(","))
|
168 |
+
interests = set(interest.strip().lower() for interest in profile["interests"].split(","))
|
169 |
+
user_answers_text = ' '.join(user_answers.values()).lower()
|
170 |
+
|
171 |
+
score = 0
|
172 |
+
|
173 |
+
if educational_background in qualifications or educational_background in job_description:
|
174 |
+
score += 2
|
175 |
+
if any(skill in skills for skill in tech_skills):
|
176 |
+
score += 3
|
177 |
+
if any(skill in job_description or role for skill in soft_skills):
|
178 |
+
score += 1
|
179 |
+
if any(interest in job_title or job_description for interest in interests):
|
180 |
+
score += 2
|
181 |
+
if any(answer in job_description or qualifications for answer in user_answers_text.split()):
|
182 |
+
score += 2
|
183 |
+
|
184 |
+
return score >= 5
|
185 |
+
|
186 |
+
# Get unique job recommendations
|
187 |
+
job_recommendations = jobs_data[jobs_data.apply(lambda row: match_job_criteria(row, profile, user_answers), axis=1)]
|
188 |
+
unique_jobs = job_recommendations.drop_duplicates(subset=['Job Title'])
|
189 |
+
|
190 |
+
# Display Job Recommendations in a table with bold job titles
|
191 |
+
st.subheader("Job Recommendations")
|
192 |
+
if not unique_jobs.empty:
|
193 |
+
job_list = unique_jobs.head(5)[['Job Title', 'Job Description']].reset_index(drop=True)
|
194 |
+
job_list['Job Title'] = job_list['Job Title'].apply(lambda x: f"<b>{x}</b>")
|
195 |
+
job_list_html = job_list.to_html(index=False, escape=False, justify='left').replace(
|
196 |
+
'<th>', '<th style="text-align: left; font-weight: bold;">')
|
197 |
+
st.markdown(job_list_html, unsafe_allow_html=True)
|
198 |
+
else:
|
199 |
+
st.write("No specific job recommendations found matching your profile.")
|
200 |
+
st.write("Here are some general job recommendations:")
|
201 |
+
fallback_jobs = jobs_data.drop_duplicates(subset=['Job Title']).head(3)
|
202 |
+
fallback_jobs['Job Title'] = fallback_jobs['Job Title'].apply(lambda x: f"<b>{x}</b>")
|
203 |
+
fallback_list_html = fallback_jobs[['Job Title', 'Job Description']].to_html(
|
204 |
+
index=False, escape=False, justify='left').replace(
|
205 |
+
'<th>', '<th style="text-align: left; font-weight: bold;">')
|
206 |
+
st.markdown(fallback_list_html, unsafe_allow_html=True)
|
207 |
+
|
208 |
+
# Course Recommendations using RAG technique
|
209 |
+
course_recommendations = courses_data[courses_data['Course Name'].apply(
|
210 |
+
lambda name: any(interest in name.lower() for interest in user_interests)
|
211 |
+
)]
|
212 |
+
|
213 |
+
# Display Course Recommendations
|
214 |
+
st.subheader("Recommended Courses")
|
215 |
+
if not course_recommendations.empty:
|
216 |
+
for _, row in course_recommendations.head(5).iterrows():
|
217 |
+
st.write(f"- [{row['Course Name']}]({row['Links']})")
|
218 |
+
else:
|
219 |
+
st.write("No specific course recommendations found matching your interests.")
|
220 |
+
st.write("Here are some general course recommendations aligned with your profile:")
|
221 |
+
|
222 |
+
fallback_courses = courses_data[
|
223 |
+
courses_data['Course Name'].apply(
|
224 |
+
lambda name: any(
|
225 |
+
word in name.lower() for word in profile["educational_background"].lower().split() +
|
226 |
+
[skill.lower() for skill in profile["tech_skills"].split(",")]
|
227 |
+
)
|
228 |
+
)
|
229 |
+
]
|
230 |
+
|
231 |
+
if not fallback_courses.empty:
|
232 |
+
for _, row in fallback_courses.head(3).iterrows():
|
233 |
+
st.write(f"- [{row['Course Name']}]({row['Links']})")
|
234 |
+
else:
|
235 |
+
st.write("Consider exploring courses in fields related to your educational background or technical skills.")
|
236 |
+
|
237 |
+
# University Recommendations Section
|
238 |
+
st.header("Top Universities")
|
239 |
+
st.write("For further education, you can explore the top universities worldwide:")
|
240 |
+
st.write(f"[View Top Universities Rankings]({universities_url})")
|
241 |
+
|
242 |
+
st.write("Thank you for using the Career Counseling Application with RAG!")
|