update
Browse files
app.py
CHANGED
@@ -1,66 +1,138 @@
|
|
1 |
-
import
|
2 |
import requests
|
|
|
|
|
|
|
|
|
3 |
|
4 |
-
# API credentials
|
5 |
API_KEY = "c1b9b6be0amsh11316ef9a922bdbp1789f5jsn18a0023eef11"
|
6 |
API_HOST = "jsearch.p.rapidapi.com"
|
7 |
|
|
|
|
|
|
|
|
|
8 |
# Function to fetch job openings
|
9 |
-
def get_job_openings(job_title, location, location_type,
|
10 |
url = "https://jsearch.p.rapidapi.com/search"
|
11 |
querystring = {
|
12 |
"query": f"{job_title} in {location}",
|
13 |
"page": "1",
|
14 |
"num_pages": "1",
|
15 |
"remote_jobs_only": "true" if location_type == "REMOTE" else "false",
|
16 |
-
"employment_types":
|
|
|
|
|
17 |
}
|
18 |
headers = {
|
19 |
"x-rapidapi-key": API_KEY,
|
20 |
"x-rapidapi-host": API_HOST
|
21 |
}
|
22 |
-
|
23 |
response = requests.get(url, headers=headers, params=querystring)
|
24 |
-
if response.status_code == 200:
|
25 |
-
|
26 |
-
|
27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
return None
|
29 |
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
st.title("🎯 Career Connect ")
|
34 |
-
st.write("Find the latest job openings based on your preferences.")
|
35 |
-
|
36 |
-
# User inputs
|
37 |
-
job_title = st.text_input("Enter Job Title:", placeholder="e.g., Node.js Developer")
|
38 |
-
location = st.text_input("Enter Location:", placeholder="e.g., New York")
|
39 |
-
location_type = st.selectbox("Location Type:", ["ANY", "ON_SITE", "REMOTE", "HYBRID"])
|
40 |
-
experience = st.selectbox("Experience Level:", ["FULLTIME", "PARTTIME", "INTERN", "CONTRACTOR"])
|
41 |
-
|
42 |
-
# Button to fetch job openings
|
43 |
-
if st.button("Search Jobs"):
|
44 |
-
if job_title and location:
|
45 |
-
with st.spinner("Fetching job openings..."):
|
46 |
-
data = get_job_openings(job_title, location, location_type, experience)
|
47 |
-
if data and 'data' in data:
|
48 |
-
st.success("Job Openings Retrieved!")
|
49 |
-
jobs = data['data']
|
50 |
-
|
51 |
-
if jobs:
|
52 |
-
for idx, job in enumerate(jobs, start=1):
|
53 |
-
st.subheader(f"{idx}. {job.get('job_title', 'No Title')}")
|
54 |
-
st.write(f"*Company:* {job.get('employer_name', 'Unknown')}")
|
55 |
-
st.write(f"*Location:* {job.get('job_city', 'Unknown')}, {job.get('job_country', '')}")
|
56 |
-
st.write(f"*Type:* {job.get('job_employment_type', 'N/A')}")
|
57 |
-
st.write(f"*Posted On:* {job.get('job_posted_at_datetime_utc', 'N/A')}")
|
58 |
-
st.write(f"*Deadline:* {job.get('job_offer_expiration_datetime_utc', 'N/A')}")
|
59 |
-
st.write(f"[🔗 View Job Posting]({job.get('job_apply_link', '#')})")
|
60 |
-
st.write("---")
|
61 |
-
else:
|
62 |
-
st.warning("No job openings found. Please try different inputs.")
|
63 |
-
else:
|
64 |
-
st.warning("No job data found. Please try again.")
|
65 |
else:
|
66 |
-
st.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
import requests
|
3 |
+
import os
|
4 |
+
import subprocess
|
5 |
+
import threading
|
6 |
+
import time
|
7 |
|
8 |
+
# API credentials for job search
|
9 |
API_KEY = "c1b9b6be0amsh11316ef9a922bdbp1789f5jsn18a0023eef11"
|
10 |
API_HOST = "jsearch.p.rapidapi.com"
|
11 |
|
12 |
+
# Securely set Groq API key (for Career Counselor)
|
13 |
+
GROQ_API_KEY = "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"
|
14 |
+
os.environ["GROQ_API_KEY"] = GROQ_API_KEY
|
15 |
+
|
16 |
# Function to fetch job openings
|
17 |
+
def get_job_openings(job_title, location, location_type, employment_type, salary_min, salary_max):
|
18 |
url = "https://jsearch.p.rapidapi.com/search"
|
19 |
querystring = {
|
20 |
"query": f"{job_title} in {location}",
|
21 |
"page": "1",
|
22 |
"num_pages": "1",
|
23 |
"remote_jobs_only": "true" if location_type == "REMOTE" else "false",
|
24 |
+
"employment_types": employment_type,
|
25 |
+
"salary_min": salary_min,
|
26 |
+
"salary_max": salary_max
|
27 |
}
|
28 |
headers = {
|
29 |
"x-rapidapi-key": API_KEY,
|
30 |
"x-rapidapi-host": API_HOST
|
31 |
}
|
|
|
32 |
response = requests.get(url, headers=headers, params=querystring)
|
33 |
+
return response.json().get('data', []) if response.status_code == 200 else f"Error {response.status_code}: {response.text}"
|
34 |
+
|
35 |
+
# Function for job search UI
|
36 |
+
def search_jobs(job_title, location, location_type, employment_type, salary_min, salary_max):
|
37 |
+
jobs = get_job_openings(job_title, location, location_type, employment_type, salary_min, salary_max)
|
38 |
+
if isinstance(jobs, str):
|
39 |
+
return jobs
|
40 |
+
if not jobs:
|
41 |
+
return "No job openings found. Please try different inputs."
|
42 |
+
|
43 |
+
return "\n\n".join(
|
44 |
+
f"{idx}. {job.get('job_title', 'No Title')}\n"
|
45 |
+
f"Company: {job.get('employer_name', 'Unknown')}\n"
|
46 |
+
f"Location: {job.get('job_city', 'Unknown')}, {job.get('job_country', '')}\n"
|
47 |
+
f"Type: {job.get('job_employment_type', 'N/A')}\n"
|
48 |
+
f"Salary: {job.get('job_salary_currency', '')} {job.get('job_salary_min', 'N/A')} - {job.get('job_salary_max', 'N/A')}\n"
|
49 |
+
f"Posted On: {job.get('job_posted_at_datetime_utc', 'N/A')}\n"
|
50 |
+
f"Deadline: {job.get('job_offer_expiration_datetime_utc', 'N/A')}\n"
|
51 |
+
f"[View Job Posting]({job.get('job_apply_link', '#')})"
|
52 |
+
for idx, job in enumerate(jobs, start=1)
|
53 |
+
)
|
54 |
+
|
55 |
+
# Function to launch Career Counselor App in a separate thread
|
56 |
+
def launch_career_counselor():
|
57 |
+
def run_streamlit():
|
58 |
+
with open("career_counselor.py", "w") as f:
|
59 |
+
f.write("""
|
60 |
+
import os
|
61 |
+
import streamlit as st
|
62 |
+
from groq import Groq
|
63 |
+
|
64 |
+
GROQ_API_KEY = os.getenv("GROQ_API_KEY")
|
65 |
+
client = Groq(api_key=GROQ_API_KEY)
|
66 |
+
|
67 |
+
st.title("Career Counselor App")
|
68 |
+
st.write("Get career guidance based on your skills, interests, and experience.")
|
69 |
+
|
70 |
+
st.header("Tell us about yourself")
|
71 |
+
skills = st.text_area("List your skills (e.g., Python, teamwork, CAD):")
|
72 |
+
interests = st.text_area("What areas of interest do you have? (e.g., AI, design, civil engineering):")
|
73 |
+
experience = st.text_area("Describe your experience (if any):")
|
74 |
+
|
75 |
+
def suggest_careers_groq(skills, interests, experience):
|
76 |
+
try:
|
77 |
+
prompt = f"Suggest careers based on Skills: {skills}, Interests: {interests}, Experience: {experience}"
|
78 |
+
chat_completion = client.chat.completions.create(
|
79 |
+
messages=[{"role": "user", "content": prompt}],
|
80 |
+
model="llama-3.3-70b-versatile",
|
81 |
+
stream=False,
|
82 |
+
)
|
83 |
+
return chat_completion.choices[0].message.content
|
84 |
+
except Exception as e:
|
85 |
+
st.error(f"Error: {e}")
|
86 |
return None
|
87 |
|
88 |
+
if st.button("Get Career Advice"):
|
89 |
+
if not skills or not interests:
|
90 |
+
st.error("Please provide skills and interests for better suggestions.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
else:
|
92 |
+
st.subheader("Career Recommendations")
|
93 |
+
response = suggest_careers_groq(skills, interests, experience)
|
94 |
+
st.write(response if response else "No recommendations available.")
|
95 |
+
st.markdown("---")
|
96 |
+
st.markdown("<p style='text-align: center;'>Designed by Career Expert</p>", unsafe_allow_html=True)
|
97 |
+
""")
|
98 |
+
|
99 |
+
subprocess.Popen(["streamlit", "run", "career_counselor.py"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
100 |
+
|
101 |
+
threading.Thread(target=run_streamlit, daemon=True).start()
|
102 |
+
|
103 |
+
# Function to handle option selection
|
104 |
+
def main(option):
|
105 |
+
if option == "Career Connect (Job Search)":
|
106 |
+
return gr.update(visible=True), gr.update(visible=False), ""
|
107 |
+
elif option == "Career Counselor App":
|
108 |
+
launch_career_counselor()
|
109 |
+
return gr.update(visible=False), gr.update(visible=True), "🚀 Career Counselor App is launching..."
|
110 |
+
|
111 |
+
# Gradio Interface
|
112 |
+
with gr.Blocks() as iface:
|
113 |
+
gr.Markdown("# 🌟 Career Guidance & Job Search")
|
114 |
+
gr.Markdown("Choose between job searching or AI-powered career guidance.")
|
115 |
+
|
116 |
+
option = gr.Radio(["Career Connect (Job Search)", "Career Counselor App"], label="Select an Option")
|
117 |
+
|
118 |
+
# Job search UI
|
119 |
+
job_search_interface = gr.Interface(
|
120 |
+
fn=search_jobs,
|
121 |
+
inputs=[
|
122 |
+
gr.Textbox(label="Enter Job Title", placeholder="e.g., Node.js Developer"),
|
123 |
+
gr.Textbox(label="Enter Location", placeholder="e.g., New York"),
|
124 |
+
gr.Radio(["ANY", "ON_SITE", "REMOTE", "HYBRID"], label="Location Type"),
|
125 |
+
gr.CheckboxGroup(["FULLTIME", "PARTTIME", "INTERN", "CONTRACTOR"], label="Select Employment Type",
|
126 |
+
value=["FULLTIME", "INTERN"]),
|
127 |
+
gr.Number(label="Minimum Salary ($)", value=0, minimum=0),
|
128 |
+
gr.Number(label="Maximum Salary ($)", value=100000, minimum=0)
|
129 |
+
],
|
130 |
+
outputs=gr.Textbox(label="Job Openings"),
|
131 |
+
visible=False
|
132 |
+
)
|
133 |
+
|
134 |
+
counselor_status = gr.Markdown("", visible=False)
|
135 |
+
|
136 |
+
option.change(main, inputs=option, outputs=[job_search_interface, counselor_status, gr.Textbox(label="Status")])
|
137 |
+
|
138 |
+
iface.launch()
|