Spaces:
Running
Running
update readme
Browse files
README.md
CHANGED
@@ -1,64 +1,136 @@
|
|
1 |
# AI-Powered Swedish Job Matching Platform
|
2 |
|
3 |
-
This repository
|
4 |
-
|
5 |
-
The final product can be seen by pressing the link below, and is hosted on Streamlit Community Cloud.
|
6 |
|
|
|
7 |
[**JobsAI**](https://jobsai.streamlit.app/)
|
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 |
-
3. The `_create_embedding` function takes an ad as an input and parses the JSON values for headline, occupation and description keys, and then combines these three into a single text. It then encodes the text with the help of a SentenceTransformer. We chose the [all-MiniLM-L6-v2](https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2). It maps sentences and paragraphs to a 384 dimensional dense vector space and is fine-tuned on [nreimers/MiniLM-l&-H384-uncased](https://huggingface.co/nreimers/MiniLM-L6-H384-uncased) to given a sentence from the pair, the model should predict which out of a set of randomly other sentences, was actually paired with it in their dataset. It is intended to be used as a sentence and short paragraph encoder.
|
37 |
-
4. The `_prepare_metadata` function extracts metadata from the ad, which is stored together with the vector embedding in the Pinecone vector database. Since some JSON values such as email and municipality were nested, we had to parse them in a nested manner.
|
38 |
-
5. When 100 ads (our batch size for insertion) have been vectorized and retrieved metadata from, we upsert all the ads to the Pinecone vector database through the `_batch_upsert` function.
|
39 |
|
40 |
-
###
|
41 |
|
42 |
-
|
|
|
|
|
43 |
|
44 |
-
|
45 |
|
46 |
-
|
|
|
47 |
|
48 |
-
|
49 |
|
50 |
-
##
|
51 |
|
52 |
-
|
53 |
-
2. Navigate to the cloned repository folder on your machine in the terminal and run `python -r requirements.txt`
|
54 |
-
3. Sign up for an account at [Pinecone](https://www.pinecone.io/) and create an API key.
|
55 |
-
4. Save the API key as a Github Actions Secret, with the name `PINECONE_API_KEY`.
|
56 |
-
5. Run `python bootstrap.py`. This may take a while since all job listings have to be retrieved from the API and then vectorized and stored in the vector database.
|
57 |
-
6. To update the vector database, run `python main.py`. This should preferebly be scheduled using e.g. Github Actions Workflow.
|
58 |
-
7. Run `streamlit run app.py` to start the Streamlit app locally, where you can interact with the application using an UI and be able to upload your own resume to find the most relevant jobs for you.
|
59 |
|
60 |
-
|
61 |
|
62 |
-
|
63 |
-
2. The [all-MiniLM-L6-v2](https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2) is not optimized for multilingual text. Many people in Sweden have their resumes in Swedish, so better performance would probably achieved with a multilingual model.
|
64 |
-
3. Users should be able to filter on municipality or location, because the current app ignores where the person wants to work (often not explicitly mentioned in their resume), making many job listings not relevant anyway.
|
|
|
1 |
# AI-Powered Swedish Job Matching Platform
|
2 |
|
3 |
+
This repository contains the final project for the course **ID2223 Scalable Machine Learning and Deep Learning** at KTH.
|
|
|
|
|
4 |
|
5 |
+
The project culminates in an AI-powered job matching platform, **JobsAI**, designed to help users find job listings tailored to their resumes. The application is hosted on Streamlit Community Cloud and can be accessed here:
|
6 |
[**JobsAI**](https://jobsai.streamlit.app/)
|
7 |
|
8 |
+
---
|
9 |
+
|
10 |
+
## Overview
|
11 |
+
|
12 |
+
### Project Pitch
|
13 |
+
|
14 |
+
Finding the right job can be overwhelming, especially with over 40,000 listings available on Arbetsförmedlingen. **JobsAI** streamlines this process by using **vector embeddings** and **similarity search** to match users’ resumes with the most relevant job postings. Say goodbye to endless scrolling and let AI do the heavy lifting!
|
15 |
+
|
16 |
+
---
|
17 |
+
|
18 |
+
## Problem Statement
|
19 |
+
|
20 |
+
Traditional job search methods often involve manual browsing of job listings, leading to inefficiency and mismatched applications. To address this, we developed an AI-powered job matching platform that:
|
21 |
+
|
22 |
+
1. **Analyzes resumes and job descriptions** to calculate compatibility scores.
|
23 |
+
2. **Recommends the most relevant job postings** based on semantic similarity.
|
24 |
+
|
25 |
+
The platform leverages **Natural Language Processing (NLP)** and machine learning to eliminate the inefficiencies of manual job searches.
|
26 |
+
|
27 |
+
### Data Sources
|
28 |
+
|
29 |
+
The platform uses two primary data sources:
|
30 |
+
|
31 |
+
1. **Job Listings**: Retrieved via Arbetsförmedlingen’s [JobStream API](https://jobstream.api.jobtechdev.se/), which provides real-time updates for job postings.
|
32 |
+
2. **Resumes**: Uploaded directly by users via the frontend application.
|
33 |
+
|
34 |
+
---
|
35 |
+
|
36 |
+
## Methodology
|
37 |
+
|
38 |
+
### Tool Selection
|
39 |
+
|
40 |
+
- **Vector Database**: After evaluating several options, we chose **Pinecone** for its ease of use and targeted support for vector embeddings.
|
41 |
+
- **Embedding Model**: We used [**sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2**](https://huggingface.co/sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2), a pre-trained transformer model that encodes sentences and paragraphs into a 384-dimensional dense vector space.
|
42 |
+
- **Backend Updates**: GitHub Actions was utilized to automate daily updates to the vector database.
|
43 |
+
|
44 |
+
### Workflow
|
45 |
+
|
46 |
+
1. **Data Retrieval**:
|
47 |
+
|
48 |
+
- Job data is fetched via the JobStream API and stored in Pinecone after being vectorized.
|
49 |
+
- Metadata such as job title, description, location, and contact details is extracted.
|
50 |
+
|
51 |
+
2. **Similarity Search**:
|
52 |
+
- User-uploaded resumes are vectorized using the same sentence transformer model.
|
53 |
+
- Pinecone is queried for the top-k most similar job embeddings, which are then displayed to the user alongside their similarity scores.
|
54 |
+
|
55 |
+
---
|
56 |
+
|
57 |
+
## Code Architecture
|
58 |
+
|
59 |
+
### First-Time Setup
|
60 |
+
|
61 |
+
1. Run `bootstrap.py` to:
|
62 |
+
- Retrieve all job listings using the JobStream API’s snapshot endpoint.
|
63 |
+
- Vectorize the listings and insert them into the Pinecone database.
|
64 |
+
2. Embeddings and metadata are generated using helper functions:
|
65 |
+
- `_create_embedding`: Combines job title, occupation, and description for encoding into a dense vector.
|
66 |
+
- `_prepare_metadata`: Extracts additional details like email, location, and timestamps for storage alongside embeddings.
|
67 |
+
|
68 |
+
### Daily Updates
|
69 |
|
70 |
+
- **Automated Workflow**: A GitHub Actions workflow runs `main.py` daily at midnight.
|
71 |
+
- **Incremental Updates**: The `keep_updated.py` function fetches job listings updated since the last recorded timestamp, ensuring the vector database remains current.
|
72 |
|
73 |
+
### Querying for Matches
|
74 |
|
75 |
+
- When a user uploads their resume:
|
76 |
+
- The resume is encoded using the same transformer model.
|
77 |
+
- Pinecone’s similarity search retrieves the top-k most relevant job listings.
|
78 |
|
79 |
+
---
|
80 |
|
81 |
+
## How to Run
|
82 |
|
83 |
+
### Prerequisites
|
84 |
|
85 |
+
1. Python 3.x installed locally.
|
86 |
+
2. A [Pinecone](https://www.pinecone.io/) account and API key.
|
87 |
+
3. Arbetsförmedlingen JobStream API access (free).
|
88 |
|
89 |
+
### Steps
|
90 |
|
91 |
+
1. Clone this repository:
|
92 |
+
```bash
|
93 |
+
git clone https://github.com/filiporestav/jobsai.git
|
94 |
+
cd jobsai
|
95 |
+
```
|
96 |
+
2. Install dependencies:
|
97 |
+
```bash
|
98 |
+
pip install -r requirements.txt
|
99 |
+
```
|
100 |
+
3. Add your Pinecone API key as an environment variable:
|
101 |
+
```bash
|
102 |
+
export PINECONE_API_KEY=<your-api-key>
|
103 |
+
```
|
104 |
+
4. Run the application locally:
|
105 |
+
```bash
|
106 |
+
streamlit run app.py
|
107 |
+
```
|
108 |
+
5. Open the Streamlit app in your browser to upload resumes and view job recommendations.
|
109 |
|
110 |
+
## Potential Improvements
|
111 |
|
112 |
+
### Model Limitation
|
113 |
|
114 |
+
- The current embedding model truncates text longer than 128 tokens.
|
115 |
+
- For longer job descriptions, a model capable of processing more tokens (e.g., 512 or 1024) could improve accuracy.
|
|
|
|
|
|
|
116 |
|
117 |
+
### Active Learning
|
118 |
|
119 |
+
- Adding a feedback loop for users to label jobs as "Relevant" or "Not Relevant" could fine-tune the model.
|
120 |
+
- Limitations in Streamlit’s reactivity make it unsuitable for collecting real-time feedback.
|
121 |
+
- A future iteration could use **React** for a more seamless UI experience.
|
122 |
|
123 |
+
### Scalability
|
124 |
|
125 |
+
- Embedding and querying currently run on CPU, which may limit performance for larger datasets.
|
126 |
+
- Switching to GPU-based processing would significantly enhance speed.
|
127 |
|
128 |
+
---
|
129 |
|
130 |
+
## Conclusion
|
131 |
|
132 |
+
**JobsAI** is a proof-of-concept platform that demonstrates how AI can revolutionize the job search experience. By leveraging vector embeddings and similarity search, the platform reduces inefficiencies and matches users with the most relevant job postings.
|
|
|
|
|
|
|
|
|
|
|
|
|
133 |
|
134 |
+
While it is functional and effective as a prototype, there are ample opportunities for enhancement, particularly in scalability, UI design, and model fine-tuning.
|
135 |
|
136 |
+
For a live demo, visit [**JobsAI**](https://jobsai.streamlit.app/).
|
|
|
|