From 67f513a0a19759c0d82d26797f09eae320ef63c8 Mon Sep 17 00:00:00 2001 From: Basil Behanan <158139580+Basilbe@users.noreply.github.com> Date: Fri, 3 Apr 2026 19:06:40 +1100 Subject: [PATCH 01/13] Create Readme.md --- Playground/Basil/Readme.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 Playground/Basil/Readme.md diff --git a/Playground/Basil/Readme.md b/Playground/Basil/Readme.md new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/Playground/Basil/Readme.md @@ -0,0 +1 @@ + From b696d6135aa0b347125adb0aa8f94c5ae6a7cb15 Mon Sep 17 00:00:00 2001 From: Basil Behanan <158139580+Basilbe@users.noreply.github.com> Date: Sat, 4 Apr 2026 19:30:30 +1100 Subject: [PATCH 02/13] Create temp --- Playground/Basil/notebooks/temp | 1 + 1 file changed, 1 insertion(+) create mode 100644 Playground/Basil/notebooks/temp diff --git a/Playground/Basil/notebooks/temp b/Playground/Basil/notebooks/temp new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/Playground/Basil/notebooks/temp @@ -0,0 +1 @@ + From b4990eda0f7fafc196f05cce46ce52472c12e59e Mon Sep 17 00:00:00 2001 From: Basil Behanan <158139580+Basilbe@users.noreply.github.com> Date: Sat, 4 Apr 2026 19:30:57 +1100 Subject: [PATCH 03/13] Create temp --- Playground/Basil/data/temp | 1 + 1 file changed, 1 insertion(+) create mode 100644 Playground/Basil/data/temp diff --git a/Playground/Basil/data/temp b/Playground/Basil/data/temp new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/Playground/Basil/data/temp @@ -0,0 +1 @@ + From dea854d51f41240112190dd5684acf4cbe92245b Mon Sep 17 00:00:00 2001 From: Basil Behanan <158139580+Basilbe@users.noreply.github.com> Date: Sat, 4 Apr 2026 19:31:18 +1100 Subject: [PATCH 04/13] Create temp --- Playground/Basil/outputs/temp | 1 + 1 file changed, 1 insertion(+) create mode 100644 Playground/Basil/outputs/temp diff --git a/Playground/Basil/outputs/temp b/Playground/Basil/outputs/temp new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/Playground/Basil/outputs/temp @@ -0,0 +1 @@ + From af20d4d96f963c3e5fe68b8b6116f6a7fc207e82 Mon Sep 17 00:00:00 2001 From: Basil Behanan <158139580+Basilbe@users.noreply.github.com> Date: Sat, 4 Apr 2026 19:31:40 +1100 Subject: [PATCH 05/13] Add files via upload --- Playground/Basil/requirements.txt | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 Playground/Basil/requirements.txt diff --git a/Playground/Basil/requirements.txt b/Playground/Basil/requirements.txt new file mode 100644 index 0000000000..9bbdaa3011 --- /dev/null +++ b/Playground/Basil/requirements.txt @@ -0,0 +1,6 @@ +pandas +numpy +matplotlib +scikit-learn +nltk +jupyter \ No newline at end of file From 8dc4332cb6f5a6e1b32966a0a701e68f1214a062 Mon Sep 17 00:00:00 2001 From: Basil Behanan <158139580+Basilbe@users.noreply.github.com> Date: Sat, 4 Apr 2026 19:33:47 +1100 Subject: [PATCH 06/13] Add files via upload --- .../Basil/notebooks/resume_job_matching.ipynb | 955 ++++++++++++++++++ 1 file changed, 955 insertions(+) create mode 100644 Playground/Basil/notebooks/resume_job_matching.ipynb diff --git a/Playground/Basil/notebooks/resume_job_matching.ipynb b/Playground/Basil/notebooks/resume_job_matching.ipynb new file mode 100644 index 0000000000..873d385964 --- /dev/null +++ b/Playground/Basil/notebooks/resume_job_matching.ipynb @@ -0,0 +1,955 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "bdf05866", + "metadata": {}, + "source": [ + "# Resume-to-Job Matching Assistant\n", + "\n", + "This notebook ranks job postings against a resume using two signals:\n", + "1. Text similarity using TF-IDF + cosine similarity\n", + "2. Skill overlap score\n", + "\n", + "The final ranking combines both into a weighted prototype score." + ] + }, + { + "cell_type": "markdown", + "id": "5bee9af4", + "metadata": {}, + "source": [ + "## Prototype Scope\n", + "\n", + "This notebook implements the baseline version of the Resume-to-Job Matching Assistant \n", + "using TF-IDF and skill overlap. It does not yet include semantic similarity or advanced \n", + "context understanding, which will be introduced in the next stage." + ] + }, + { + "cell_type": "markdown", + "id": "cade8ac8", + "metadata": {}, + "source": [ + "## 1) Imports and Setup\n", + "Load required libraries for data handling, NLP preprocessing, matching, and visualization." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "b13e4126", + "metadata": {}, + "outputs": [], + "source": [ + "import re\n", + "import string\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import nltk\n", + "import pandas as pd\n", + "from nltk.corpus import stopwords\n", + "from nltk.tokenize import word_tokenize\n", + "from sklearn.feature_extraction.text import TfidfVectorizer\n", + "from sklearn.metrics.pairwise import cosine_similarity" + ] + }, + { + "cell_type": "markdown", + "id": "e72bd365", + "metadata": {}, + "source": [ + "## 2) Load Input Data\n", + "Read the resume text and job postings dataset, then preview both." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "a70aef31", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Resume loaded successfully.\n", + "Resume preview:\n", + "Basil Behanan\n", + "Tel: +61 468410310\n", + "Email: Basilbehanan5@gmail.com\n", + "LinkedIn: LinkedIn\n", + "\n", + "Career Profile\n", + "Final-year Computer Science student majoring in Data Science with experience applying data analytics, machine learning, and data engineering techniques to solve complex problems. Skilled in extracting,\n", + "\n", + "Jobs loaded successfully.\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
job_idtitlecompanydescription
01Data AnalystCompany ALooking for a candidate with experience in Pyt...
12Junior Data ScientistCompany BSeeking a graduate with experience in machine ...
23Machine Learning InternCompany CThe ideal applicant has worked on machine lear...
34AI Engineer InternCompany DLooking for students with exposure to deep lea...
45Business Intelligence AnalystCompany ECandidates should have knowledge of SQL, repor...
\n", + "
" + ], + "text/plain": [ + " job_id title company \\\n", + "0 1 Data Analyst Company A \n", + "1 2 Junior Data Scientist Company B \n", + "2 3 Machine Learning Intern Company C \n", + "3 4 AI Engineer Intern Company D \n", + "4 5 Business Intelligence Analyst Company E \n", + "\n", + " description \n", + "0 Looking for a candidate with experience in Pyt... \n", + "1 Seeking a graduate with experience in machine ... \n", + "2 The ideal applicant has worked on machine lear... \n", + "3 Looking for students with exposure to deep lea... \n", + "4 Candidates should have knowledge of SQL, repor... " + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "with open(\"../data/resume.txt\", \"r\", encoding=\"utf-8\") as file:\n", + " resume_text = file.read()\n", + "\n", + "jobs_df = pd.read_csv(\"../data/jobs.csv\")\n", + "\n", + "print(\"Resume loaded successfully.\")\n", + "print(\"Resume preview:\")\n", + "print(resume_text[:300])\n", + "print(\"\\nJobs loaded successfully.\")\n", + "jobs_df.head()" + ] + }, + { + "cell_type": "markdown", + "id": "4ec6a475", + "metadata": {}, + "source": [ + "## 3) Text Preprocessing\n", + "Normalize text by lowercasing, removing punctuation, tokenizing, and dropping stopwords." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "64026f08", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[nltk_data] Downloading package punkt to\n", + "[nltk_data] C:\\Users\\bazil\\AppData\\Roaming\\nltk_data...\n", + "[nltk_data] Package punkt is already up-to-date!\n", + "[nltk_data] Downloading package stopwords to\n", + "[nltk_data] C:\\Users\\bazil\\AppData\\Roaming\\nltk_data...\n", + "[nltk_data] Package stopwords is already up-to-date!\n" + ] + } + ], + "source": [ + "nltk.download(\"punkt\")\n", + "nltk.download(\"stopwords\")\n", + "\n", + "stop_words = set(stopwords.words(\"english\"))\n", + "\n", + "def preprocess_text(text):\n", + " text = text.lower()\n", + " text = text.translate(str.maketrans(\"\", \"\", string.punctuation))\n", + " text = re.sub(r\"\\s+\", \" \", text).strip()\n", + " tokens = word_tokenize(text)\n", + " cleaned_tokens = [word for word in tokens if word.isalpha() and word not in stop_words]\n", + " return \" \".join(cleaned_tokens)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "505e7fac", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Preprocessing complete.\n", + "Number of jobs processed: 5\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
titlecompanycleaned_description
0Data AnalystCompany Alooking candidate experience python sql dashbo...
1Junior Data ScientistCompany Bseeking graduate experience machine learning p...
2Machine Learning InternCompany Cideal applicant worked machine learning projec...
3AI Engineer InternCompany Dlooking students exposure deep learning nlp py...
4Business Intelligence AnalystCompany Ecandidates knowledge sql reporting dashboard c...
\n", + "
" + ], + "text/plain": [ + " title company \\\n", + "0 Data Analyst Company A \n", + "1 Junior Data Scientist Company B \n", + "2 Machine Learning Intern Company C \n", + "3 AI Engineer Intern Company D \n", + "4 Business Intelligence Analyst Company E \n", + "\n", + " cleaned_description \n", + "0 looking candidate experience python sql dashbo... \n", + "1 seeking graduate experience machine learning p... \n", + "2 ideal applicant worked machine learning projec... \n", + "3 looking students exposure deep learning nlp py... \n", + "4 candidates knowledge sql reporting dashboard c... " + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cleaned_resume_text = preprocess_text(resume_text)\n", + "jobs_df[\"cleaned_description\"] = jobs_df[\"description\"].apply(preprocess_text)\n", + "cleaned_job_texts = jobs_df[\"cleaned_description\"].tolist()\n", + "\n", + "print(\"Preprocessing complete.\")\n", + "print(f\"Number of jobs processed: {len(cleaned_job_texts)}\")\n", + "jobs_df[[\"title\", \"company\", \"cleaned_description\"]].head()" + ] + }, + { + "cell_type": "markdown", + "id": "fe4e5a64", + "metadata": {}, + "source": [ + "## 4) Text Similarity Matching\n", + "Use TF-IDF vectors and cosine similarity to score each job against the resume." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "2d702d30", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
titlecompanymatch_percentage
1Junior Data ScientistCompany B30.77
2Machine Learning InternCompany C22.43
3AI Engineer InternCompany D18.68
0Data AnalystCompany A12.12
4Business Intelligence AnalystCompany E4.05
\n", + "
" + ], + "text/plain": [ + " title company match_percentage\n", + "1 Junior Data Scientist Company B 30.77\n", + "2 Machine Learning Intern Company C 22.43\n", + "3 AI Engineer Intern Company D 18.68\n", + "0 Data Analyst Company A 12.12\n", + "4 Business Intelligence Analyst Company E 4.05" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "all_documents = [cleaned_resume_text] + cleaned_job_texts\n", + "vectorizer = TfidfVectorizer()\n", + "tfidf_matrix = vectorizer.fit_transform(all_documents)\n", + "\n", + "resume_vector = tfidf_matrix[0:1]\n", + "job_vectors = tfidf_matrix[1:]\n", + "similarity_scores = cosine_similarity(resume_vector, job_vectors)[0]\n", + "\n", + "jobs_df[\"similarity_score\"] = similarity_scores\n", + "jobs_df[\"match_percentage\"] = (jobs_df[\"similarity_score\"] * 100).round(2)\n", + "\n", + "jobs_df[[\"title\", \"company\", \"match_percentage\"]].sort_values(\n", + " by=\"match_percentage\", ascending=False\n", + ").head()" + ] + }, + { + "cell_type": "markdown", + "id": "fc5e71b0", + "metadata": {}, + "source": [ + "## 5) Skill Extraction and Overlap\n", + "Extract known skills from both resume and jobs, then compute matched and missing skills.\n", + "\n", + "Note: Skill extraction is based on direct string matching and may fail for synonyms or variations in wording" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "71deeea3", + "metadata": {}, + "outputs": [], + "source": [ + "skill_list = [\n", + " \"python\", \"sql\", \"excel\", \"tableau\", \"power bi\", \"machine learning\",\n", + " \"deep learning\", \"data analysis\", \"data visualization\", \"nlp\",\n", + " \"computer vision\", \"opencv\", \"yolo\", \"pandas\", \"numpy\",\n", + " \"scikit-learn\", \"tensorflow\", \"pytorch\", \"git\", \"aws\",\n", + " \"feature engineering\", \"model evaluation\", \"dashboard\", \"reporting\",\n", + " \"statistics\", \"data preprocessing\", \"business intelligence\"\n", + "]\n", + "\n", + "def extract_skills(text, skills):\n", + " text = text.lower()\n", + " return sorted({skill for skill in skills if skill in text})\n", + "\n", + "def compare_skills(resume_skills, job_skills):\n", + " matched = sorted(set(resume_skills).intersection(set(job_skills)))\n", + " missing = sorted(set(job_skills) - set(resume_skills))\n", + " return matched, missing\n", + "\n", + "def skill_overlap_score(job_skills, matched_skills):\n", + " return 0 if not job_skills else len(matched_skills) / len(job_skills)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "ab8962f6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
titlematched_skillsmissing_skillsskill_overlap_score
0Data Analyst[power bi, python, sql][dashboard, data visualization, reporting, tab...42.86
1Junior Data Scientist[feature engineering, machine learning, model ...[data preprocessing]80.00
2Machine Learning Intern[computer vision, machine learning, python][]100.00
3AI Engineer Intern[python][deep learning, nlp]33.33
4Business Intelligence Analyst[excel, power bi, sql][dashboard, reporting]60.00
\n", + "
" + ], + "text/plain": [ + " title \\\n", + "0 Data Analyst \n", + "1 Junior Data Scientist \n", + "2 Machine Learning Intern \n", + "3 AI Engineer Intern \n", + "4 Business Intelligence Analyst \n", + "\n", + " matched_skills \\\n", + "0 [power bi, python, sql] \n", + "1 [feature engineering, machine learning, model ... \n", + "2 [computer vision, machine learning, python] \n", + "3 [python] \n", + "4 [excel, power bi, sql] \n", + "\n", + " missing_skills skill_overlap_score \n", + "0 [dashboard, data visualization, reporting, tab... 42.86 \n", + "1 [data preprocessing] 80.00 \n", + "2 [] 100.00 \n", + "3 [deep learning, nlp] 33.33 \n", + "4 [dashboard, reporting] 60.00 " + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "resume_skills = extract_skills(cleaned_resume_text, skill_list)\n", + "jobs_df[\"job_skills\"] = jobs_df[\"cleaned_description\"].apply(lambda x: extract_skills(x, skill_list))\n", + "\n", + "jobs_df[[\"matched_skills\", \"missing_skills\"]] = jobs_df.apply(\n", + " lambda row: pd.Series(compare_skills(resume_skills, row[\"job_skills\"])), axis=1\n", + ")\n", + "\n", + "jobs_df[\"skill_overlap_score\"] = (\n", + " jobs_df.apply(lambda row: skill_overlap_score(row[\"job_skills\"], row[\"matched_skills\"]), axis=1) * 100\n", + ").round(2)\n", + "\n", + "jobs_df[[\"title\", \"matched_skills\", \"missing_skills\", \"skill_overlap_score\"]].head()" + ] + }, + { + "cell_type": "markdown", + "id": "d8d3e374", + "metadata": {}, + "source": [ + "## 6) Final Scoring and Ranking\n", + "Create a combined prototype score and build the final ranked results table." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "2b4ae0ff", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
titlecompanymatch_percentageskill_overlap_scoreprototype_scorematched_skillsmissing_skills
0Machine Learning InternCompany C22.43100.0045.70computer vision, machine learning, pythonNone
1Junior Data ScientistCompany B30.7780.0045.54feature engineering, machine learning, model e...data preprocessing
2AI Engineer InternCompany D18.6833.3323.07pythondeep learning, nlp
3Data AnalystCompany A12.1242.8621.34power bi, python, sqldashboard, data visualization, reporting, tableau
4Business Intelligence AnalystCompany E4.0560.0020.84excel, power bi, sqldashboard, reporting
\n", + "
" + ], + "text/plain": [ + " title company match_percentage \\\n", + "0 Machine Learning Intern Company C 22.43 \n", + "1 Junior Data Scientist Company B 30.77 \n", + "2 AI Engineer Intern Company D 18.68 \n", + "3 Data Analyst Company A 12.12 \n", + "4 Business Intelligence Analyst Company E 4.05 \n", + "\n", + " skill_overlap_score prototype_score \\\n", + "0 100.00 45.70 \n", + "1 80.00 45.54 \n", + "2 33.33 23.07 \n", + "3 42.86 21.34 \n", + "4 60.00 20.84 \n", + "\n", + " matched_skills \\\n", + "0 computer vision, machine learning, python \n", + "1 feature engineering, machine learning, model e... \n", + "2 python \n", + "3 power bi, python, sql \n", + "4 excel, power bi, sql \n", + "\n", + " missing_skills \n", + "0 None \n", + "1 data preprocessing \n", + "2 deep learning, nlp \n", + "3 dashboard, data visualization, reporting, tableau \n", + "4 dashboard, reporting " + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "jobs_df[\"prototype_score\"] = (\n", + " 0.7 * jobs_df[\"match_percentage\"] + 0.3 * jobs_df[\"skill_overlap_score\"]\n", + ").round(2)\n", + "\n", + "ranked_jobs = jobs_df.sort_values(by=\"prototype_score\", ascending=False).reset_index(drop=True)\n", + "\n", + "final_results = ranked_jobs[[\n", + " \"title\",\n", + " \"company\",\n", + " \"match_percentage\",\n", + " \"skill_overlap_score\",\n", + " \"prototype_score\",\n", + " \"matched_skills\",\n", + " \"missing_skills\",\n", + "]].copy()\n", + "\n", + "final_results[\"matched_skills\"] = final_results[\"matched_skills\"].apply(\n", + " lambda x: \", \".join(x) if isinstance(x, list) and x else \"None\"\n", + ")\n", + "final_results[\"missing_skills\"] = final_results[\"missing_skills\"].apply(\n", + " lambda x: \", \".join(x) if isinstance(x, list) and x else \"None\"\n", + ")\n", + "\n", + "final_results" + ] + }, + { + "cell_type": "markdown", + "id": "6520abe1", + "metadata": {}, + "source": [ + "## Scoring Strategy Justification\n", + "\n", + "The prototype score combines text similarity (70%) and skill overlap (30%). \n", + "Text similarity is given higher weight because TF-IDF captures overall alignment \n", + "between the resume and job description, while skill overlap provides interpretability \n", + "by highlighting specific matching and missing skills.\n", + "\n", + "The weights are heuristic and not learned from data. They are chosen to balance \n", + "global text similarity with explicit skill matching. In future work, these weights \n", + "could be tuned or learned from real hiring data." + ] + }, + { + "cell_type": "markdown", + "id": "a6cbf933", + "metadata": {}, + "source": [ + "## 7) Reporting, Visualization, and Export\n", + "Present ranked output, plot scores, and save artifacts to the outputs folder." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "6ce403cb", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Resume-to-Job Matching Assistant - Prototype Results\n", + "\n", + "Rank 1: Machine Learning Intern at Company C\n", + "Text Match Score: 22.43%\n", + "Skill Overlap Score: 100.0%\n", + "Prototype Score: 45.7%\n", + "Matched Skills: computer vision, machine learning, python\n", + "Missing Skills: None\n", + "--------------------------------------------------------------------------------\n", + "Rank 2: Junior Data Scientist at Company B\n", + "Text Match Score: 30.77%\n", + "Skill Overlap Score: 80.0%\n", + "Prototype Score: 45.54%\n", + "Matched Skills: feature engineering, machine learning, model evaluation, python\n", + "Missing Skills: data preprocessing\n", + "--------------------------------------------------------------------------------\n", + "Rank 3: AI Engineer Intern at Company D\n", + "Text Match Score: 18.68%\n", + "Skill Overlap Score: 33.33%\n", + "Prototype Score: 23.07%\n", + "Matched Skills: python\n", + "Missing Skills: deep learning, nlp\n", + "--------------------------------------------------------------------------------\n", + "Rank 4: Data Analyst at Company A\n", + "Text Match Score: 12.12%\n", + "Skill Overlap Score: 42.86%\n", + "Prototype Score: 21.34%\n", + "Matched Skills: power bi, python, sql\n", + "Missing Skills: dashboard, data visualization, reporting, tableau\n", + "--------------------------------------------------------------------------------\n", + "Rank 5: Business Intelligence Analyst at Company E\n", + "Text Match Score: 4.05%\n", + "Skill Overlap Score: 60.0%\n", + "Prototype Score: 20.84%\n", + "Matched Skills: excel, power bi, sql\n", + "Missing Skills: dashboard, reporting\n", + "--------------------------------------------------------------------------------\n" + ] + } + ], + "source": [ + "print(\"Resume-to-Job Matching Assistant - Prototype Results\\n\")\n", + "for i, row in final_results.iterrows():\n", + " print(f\"Rank {i + 1}: {row['title']} at {row['company']}\")\n", + " print(f\"Text Match Score: {row['match_percentage']}%\")\n", + " print(f\"Skill Overlap Score: {row['skill_overlap_score']}%\")\n", + " print(f\"Prototype Score: {row['prototype_score']}%\")\n", + " print(f\"Matched Skills: {row['matched_skills']}\")\n", + " print(f\"Missing Skills: {row['missing_skills']}\")\n", + " print(\"-\" * 80)" + ] + }, + { + "cell_type": "markdown", + "id": "d19803b8", + "metadata": {}, + "source": [ + "## Result Evaluation\n", + "\n", + "The ranking produced by the prototype shows that roles aligned with data science \n", + "and machine learning receive higher scores, which is consistent with the candidate’s \n", + "background. Roles requiring business intelligence or reporting tools rank lower \n", + "when fewer matching skills are present.\n", + "\n", + "However, some limitations are observed:\n", + "- Jobs with similar meaning but different wording may receive lower scores\n", + "- Skill matching depends on exact phrase matching\n", + "- Some relevant skills may not be captured in the predefined skill list\n", + "\n", + "These observations highlight the limitations of keyword-based approaches and \n", + "motivate the need for semantic similarity in the next stage." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "817c377a", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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PHiwsmfPLl9fX40cOdJuv5LUsmVL2Ww2870kffvtt3ruuefk6uqqQoUKadSoUYqPjzeX22w2zZ49W82bN5eHh4fGjh1rnp/58+crMDBQPj4+ateuna5evZquegEAAAA8+dIdur28vOTj45PmC9ZbvHixihcvruLFi6tjx44KDw+37Pb/oUOHatCgQYqOjlaxYsXUvn17M0hu3rxZPXv2VL9+/RQdHa169epp3Lhx993nhg0bdOTIEW3YsEGRkZGKiIiw++Cga9eu2rx5sxYtWqQ9e/aodevWatCggQ4dOiRJ2rt3r+rXr69WrVppz549Wrx4sX766Sf16dPHrp8pU6aodOnS2rlzp4YNG5buY46MjJSHh4e2bdumyZMna/To0Vq7dq0kKSoqSpIUHh6uuLg48/3q1avVsWNH9e3bV/v379cnn3yiiIiIZOdjxIgRat68ufbu3atu3bpJko4cOaJly5ZpxYoVWrFihTZt2qSJEyemu14AAAAATzabkY7E5uDgoNOnTyt37tyPoyakoXr16mrTpo369eun+Ph4+fn56fPPP1fdunUl3RmlLliwoH755ZdUJzELCQnRli1bkt1y/dFHH6lLly7mPubOnatXX31VkrR//36VKlVKMTExCgoKUrt27XTt2jWtWLHC3L5jx45asWKFLl26JOnOSPeyZcvM58tDQ0O1ceNGHTlyRFmyZJEktWnTRg4ODlq0aJGOHDmiokWL6vfff5e/v7+537p166py5coaP368OnfuLDc3N33yySfm8p9++km1atXS9evX5erqqsDAQJUvX15ff/11mucyNDRUly5dMp/RDgkJUUJCgn788UdzncqVK6tOnTpmELbZbPr666/tngWvWbOmGjZsqCFDhphtn332mQYPHqw//vjD3K5///567733zHVGjhypKVOm6PTp0/Ly8pIkDR48WD/88IN+/vnnFGu+efOmbt68ab6/cuWKAgICFNB/iRxcMvbxAABA+sVObJzZJQAAHrMrV67Ix8dHly9fNu8aTkm6nunmee4nw4EDB7R9+3YtXbpUkuTo6Ki2bdsqLCzMDN3p1aFDBw0dOtSu7d4PVYKDg83/9vPzkySdPXtWQUFBOnDggFq2bGm3fuXKle1CeEpKlSplBu6k/e7du1eStGvXLhmGoWLFitltc/PmTeXIkUOStHPnTh0+fFgLFiwwlxuGocTERB07dkwlSpSQJFWsWDHNOlJz9zEn1Xf27Nk0t9m5c6eioqLsRrYTEhL0999/68aNG+az8inVFBgYaAbu9PQ3YcIEjRo1Kl3HAgAAACDzpSt0M3v5k2HevHmKj49X3rx5zTbDMOTk5KQ///xT2bJlS/e+fHx8VKRIkTTXuXuir6QPXhITE81+7/0wJj3Xyb2Th9lsNnOfiYmJypIli3bu3GkXzCWZE7IlJibq9ddfV9++fZPt++4J5Tw8PO5by4PWl5rExESNGjUqxXkNXF1d06zpQfsbMmSIBg4caL5PGukGAAAA8GRKV+jesGGDsmfPbnUtSEN8fLw+/fRTTZs2TS+++KLdspdeekkLFixI9lyzlYKCgrR9+3a7th07djzSPsuXL6+EhASdPXtWNWrUSHGdChUq6Ndff73vBwZWcXJyUkJCQrKaDhw48FhqcnFxkYuLi+X9AAAAAMgY6QrdtWrVsroO3MeKFSv0559/6tVXX002ad3LL7+sefPmPVDovnHjhk6fPm3X5uLiku7R8jfffFM1a9bU9OnT1bRpU61fv14rV658pEcRihUrpg4dOqhz586aNm2aypcvr/Pnz2v9+vUqU6aMGjVqpLffflvPP/+8evfurR49esjDw0MxMTFau3atPvjgg4fuO70CAwO1bt06Va9e3Txfw4cPV5MmTRQQEKDWrVvLwcFBe/bs0d69ezV27FjLawIAAADw5Er37OXIXPPmzVPdunVTnCX+pZdeUnR0tHbt2pXu/c2ZM0d+fn52r/bt26d7++rVq2v27NmaPn26ypYtq1WrVmnAgAF2t1M/jPDwcHXu3FlvvfWWihcvrmbNmmnbtm3mLdTBwcHatGmTDh06pBo1aqh8+fIaNmyY+cy51aZNm6a1a9cqICBA5cuXlyTVr19fK1as0Nq1a1WpUiU9//zzmj59ugoUKPBYagIAAADw5ErX7OVAevTo0UO//fab3ezfsFbSjInMXg4AmYvZywHgnydDZy8HUjJ16lTVq1dPHh4eWrlypSIjIzVr1qzMLgsAAAAAnhgPHLoTEhL09ddfKyYmRjabTUFBQWrRooUcHcnv/zTbt2/X5MmTdfXqVRUqVEgzZ85U9+7dM7ssAAAAAHhiPFBS3rdvn5o3b67Tp0+rePHikqSDBw8qV65cWr58ucqUKWNJkXgyLVmyJLNLAAAAAIAn2gNNpNa9e3eVKlVKv//+u3bt2qVdu3bp5MmTCg4O1muvvWZVjQAAAAAAPJUeaKR79+7d2rFjh93XSmXLlk3jxo1TpUqVMrw4AAAAAACeZg800l28eHGdOXMmWfvZs2dVpEiRDCsKAAAAAIBnwX1D95UrV8zX+PHj1bdvX3355Zf6/fff9fvvv+vLL79U//79NWnSpMdRLwAAAAAAT4373l6eNWtW2Ww2871hGGrTpo3ZlvQ1302bNlVCQoJFZQIAAAAA8PS5b+jesGHD46gDAAAAAIBnzn1Dd61atR5HHQAAAAAAPHMeaPZySbp06ZLmzZunmJgY2Ww2lSxZUt26dZOPj48V9QEAAAAA8NR6oNnLd+zYocKFC+u9997TxYsXdf78eU2fPl2FCxfWrl27rKoRAAAAAICn0gONdA8YMEDNmjXTnDlz5Oh4Z9P4+Hh1795d/fv31w8//GBJkQAAAAAAPI0eKHTv2LHDLnBLkqOjowYPHqyKFStmeHEAAAAAADzNHuj2cm9vb504cSJZ+8mTJ+Xl5ZVhRQEAAAAA8Cx4oNDdtm1bvfrqq1q8eLFOnjyp33//XYsWLVL37t3Vvn17q2oEAAAAAOCp9EC3l0+dOlU2m02dO3dWfHy8DMOQs7Oz3njjDU2cONGqGgEAAAAAeCo9UOh2dnbWjBkzNGHCBB05ckSGYahIkSJyd3e3qj4AAAAAAJ5a6QrdrVq1uv+OHB3l6+urevXqqWnTpo9cGAAAAAAAT7t0PdPt4+Nz35ebm5sOHTqktm3bavjw4VbXDQAAAADAEy9dI93h4eHp3uF3332nN954Q6NHj37oogAAAAAAeBY80Ozl6VG9enW+sxsAAAAAAFkQurNmzaqlS5dm9G4BAAAAAHjqZHjoBgAAAAAAdxC6AQAAAACwCKEbAAAAAACLELoBAAAAALAIoRsAAAAAAIsQugEAAAAAsAihGwAAAAAAixC6AQAAAACwCKEbAAAAAACLOGZ2AQAe3b5R9eXt7Z3ZZQAAAAC4ByPdAAAAAABYhNANAAAAAIBFCN0AAAAAAFiE0A0AAAAAgEUI3QAAAAAAWITQDQAAAACARQjdAAAAAABYhNANAAAAAIBFCN0AAAAAAFiE0A0AAAAAgEUI3QAAAAAAWITQDQAAAACARQjdAAAAAABYhNANAAAAAIBFCN0AAAAAAFiE0A0AAAAAgEUI3QAAAAAAWITQDQAAAACARRwzuwAAj670iNVycHHP7DIA4IkTO7FxZpcAAPiHY6QbAAAAAACLELoBAAAAALAIoRsAAAAAAIsQugEAAAAAsAihGwAAAAAAixC6AQAAAACwCKEbAAAAAACLELoBAAAAALAIoRsAAAAAAIsQugEAAAAAsAihGwAAAAAAixC6AQAAAACwCKEbAAAAAACLELoBAAAAALAIoRsAAAAAAIsQugEAAAAAsAihGwAAAAAAixC6AQAAAACwCKEbAAAAAACLELoBAAAAALAIoRsAAAAAAIsQugEAAAAAsAihGwAAAAAAixC6AQAAAACwCKEbAAAAAACLELoBAAAAALAIoRsAAAAAAIsQugEAAAAAsAihGwAAAAAAixC6AQAAAACwCKEbAAAAAACLELoBAAAAALAIoRt4BDabTcuWLcvsMgAAAAA8oQjdeGihoaGy2Wyy2WxycnJSnjx5VK9ePYWFhSkxMfGB9hUREaGsWbNmaH0LFy5UlixZ1LNnzwzdr1VCQkLUv3//zC4DAAAAQAYidOORNGjQQHFxcYqNjdXKlStVu3Zt9evXT02aNFF8fHym1hYWFqbBgwdr0aJFunHjRqbWAgAAAOCfidCNR+Li4iJfX1/lzZtXFSpU0LvvvqtvvvlGK1euVEREhLne9OnTVaZMGXl4eCggIEC9evXStWvXJEkbN25U165ddfnyZXPkfOTIkZKkzz77TBUrVpSXl5d8fX31yiuv6OzZs/etKzY2Vlu2bNE777yjoKAgffnll3bLk0bWV69erRIlSsjT09P8ACFJVFSU6tWrp5w5c8rHx0e1atXSrl27Uu2zTp066tOnj13bhQsX5OLiovXr10uSZs2apaJFi8rV1VV58uTRyy+/LOnOXQObNm3SjBkzzHMQGxt73+MEAAAA8GQjdCPD1alTR2XLltXSpUvNNgcHB82cOVP79u1TZGSk1q9fr8GDB0uSqlWrpvfff1/e3t6Ki4tTXFycBg0aJEm6deuWxowZo927d2vZsmU6duyYQkND71tDWFiYGjduLB8fH3Xs2FHz5s1Lts6NGzc0depUzZ8/Xz/88INOnDhh9itJV69eVZcuXfTjjz/q559/VtGiRdWoUSNdvXo1xT67d++uhQsX6ubNm2bbggUL5O/vr9q1a2vHjh3q27evRo8erQMHDmjVqlWqWbOmJGnGjBmqWrWqevToYZ6DgICAZH3cvHlTV65csXsBAAAAeHI5ZnYBeDYFBQVpz5495vu7n1UuWLCgxowZozfeeEOzZs2Ss7OzfHx8ZLPZ5Ovra7efbt26mf9dqFAhzZw5U5UrV9a1a9fk6emZYt+JiYmKiIjQBx98IElq166dBg4cqMOHD6tIkSLmerdv39bs2bNVuHBhSVKfPn00evRoc3mdOnXs9vvJJ58oW7Zs2rRpk5o0aZKs35deeklvvvmmvvnmG7Vp00aSFB4ebj77fuLECXl4eKhJkyby8vJSgQIFVL58eUmSj4+PnJ2d5e7unuwc3G3ChAkaNWpUqssBAAAAPFkY6YYlDMOQzWYz32/YsEH16tVT3rx55eXlpc6dO+vChQu6fv16mvv55Zdf1Lx5cxUoUEBeXl4KCQmRJJ04cSLVbdasWaPr16+rYcOGkqScOXPqxRdfVFhYmN167u7uZuCWJD8/P7tb18+ePauePXuqWLFi8vHxkY+Pj65du5Zq3y4uLurYsaPZT3R0tHbv3m2OzNerV08FChRQoUKF1KlTJy1YsOCBnzUfMmSILl++bL5Onjz5QNsDAAAAeLwI3bBETEyMChYsKEk6fvy4GjVqpNKlS+urr77Szp079dFHH0m6M9qcmuvXr+vFF1+Up6enPvvsM0VFRenrr7+WdOe289SEhYXp4sWLcnd3l6OjoxwdHfX9998rMjJSCQkJ5npOTk5229lsNhmGYb4PDQ3Vzp079f7772vLli2Kjo5Wjhw50uy7e/fuWrt2rX7//XeFhYXphRdeUIECBSRJXl5e2rVrlz7//HP5+flp+PDhKlu2rC5dupTq/u7l4uIib29vuxcAAACAJxehGxlu/fr12rt3r1566SVJ0o4dOxQfH69p06bp+eefV7FixfTHH3/YbePs7GwXiCXpt99+0/nz5zVx4kTVqFFDQUFB951E7cKFC/rmm2+0aNEiRUdH272uXbumlStXpvs4fvzxR/Xt21eNGjVSqVKl5OLiovPnz6e5TZkyZVSxYkXNmTNHCxcutLs9XpIcHR1Vt25dTZ48WXv27FFsbKw5yVpK5wAAAADA041nuvFIbt68qdOnTyshIUFnzpzRqlWrNGHCBDVp0kSdO3eWJBUuXFjx8fH64IMP1LRpU23evFmzZ8+2209gYKCuXbumdevWqWzZsnJ3d1f+/Pnl7OysDz74QD179tS+ffs0ZsyYNOuZP3++cuTIodatW8vBwf4zpSZNmmjevHkpPo+dkiJFimj+/PmqWLGirly5on//+99yc3O773bdu3dXnz595O7urpYtW5rtK1as0NGjR1WzZk1ly5ZN33//vRITE1W8eHHzHGzbtk2xsbHy9PRU9uzZkx0DAAAAgKcLf9HjkaxatUp+fn4KDAxUgwYNtGHDBs2cOVPffPONsmTJIkkqV66cpk+frkmTJql06dJasGCBJkyYYLefatWqqWfPnmrbtq1y5cqlyZMnK1euXIqIiNAXX3yhkiVLauLEiZo6dWqa9YSFhally5YphtWXXnpJK1as0JkzZ9J1bGFhYfrzzz9Vvnx5derUSX379lXu3Lnvu1379u3l6OioV155Ra6urmZ71qxZtXTpUtWpU0clSpTQ7Nmz9fnnn6tUqVKSpEGDBilLliwqWbKkcuXKleZz6wAAAACeDjbj7odYATyykydPKjAwUFFRUapQoYKlfV25ckU+Pj4K6L9EDi7ulvYFAE+j2ImNM7sEAMAzKulv8cuXL6c51xK3lwMZ5Pbt24qLi9M777yj559/3vLADQAAAODJx+3lQAbZvHmzChQooJ07dyZ7Zh0AAADAPxMj3UAGCQkJEU9rAAAAALgbI90AAAAAAFiE0A0AAAAAgEUI3QAAAAAAWITQDQAAAACARQjdAAAAAABYhNANAAAAAIBFCN0AAAAAAFiE0A0AAAAAgEUI3QAAAAAAWITQDQAAAACARQjdAAAAAABYhNANAAAAAIBFCN0AAAAAAFiE0A0AAAAAgEUI3QAAAAAAWITQDQAAAACARQjdAAAAAABYhNANAAAAAIBFCN0AAAAAAFiE0A0AAAAAgEUI3QAAAAAAWITQDQAAAACARQjdAAAAAABYhNANAAAAAIBFCN0AAAAAAFiE0A0AAAAAgEUI3QAAAAAAWITQDQAAAACARQjdAAAAAABYxDGzCwDw6PaNqi9vb+/MLgMAAADAPRjpBgAAAADAIoRuAAAAAAAsQugGAAAAAMAihG4AAAAAACxC6AYAAAAAwCKEbgAAAAAALELoBgAAAADAIoRuAAAAAAAsQugGAAAAAMAihG4AAAAAACxC6AYAAAAAwCKEbgAAAAAALELoBgAAAADAIoRuAAAAAAAsQugGAAAAAMAihG4AAAAAACxC6AYAAAAAwCKEbgAAAAAALOKY2QUAeHSlR6yWg4t7ZpcBAI9d7MTGmV0CAABpYqQbAAAAAACLELoBAAAAALAIoRsAAAAAAIsQugEAAAAAsAihGwAAAAAAixC6AQAAAACwCKEbAAAAAACLELoBAAAAALAIoRsAAAAAAIsQugEAAAAAsAihGwAAAAAAixC6AQAAAACwCKEbAAAAAACLELoBAAAAALAIoRsAAAAAAIsQugEAAAAAsAihGwAAAAAAixC6AQAAAACwCKEbAAAAAACLELoBAAAAALAIoRsAAAAAAIsQugEAAAAAsAihGwAAAAAAixC6AQAAAACwCKEbAAAAAACLELoBAAAAALAIoRsAAAAAAIsQugEAAAAAsAihGwAAAAAAixC6AQAAAACwCKEbAAAAAACLELoBAAAAALDIMx+6N27cKJvNpkuXLmV2KZkuJCRE/fv3N98HBgbq/fffN9/bbDYtW7bssdf1NAsNDVWLFi0yuwwAAAAAT6hMDd2hoaGy2WzmK0eOHGrQoIH27NmTYX1Uq1ZNcXFx8vHxybB9ZqSIiAhlzZr1gba5NzxnlLi4ODVs2DDD95tZ/vrrL2XLlk3Zs2fXX3/9ldnl3NfDXAsAAAAAnmyZPtLdoEEDxcXFKS4uTuvWrZOjo6OaNGmSYft3dnaWr6+vbDZbhu3zWeXr6ysXF5fMLiPDfPXVVypdurRKliyppUuXZnY5AAAAAP6BMj10u7i4yNfXV76+vipXrpzefvttnTx5UufOnZOU8u3h0dHRstlsio2NlSQdP35cTZs2VbZs2eTh4aFSpUrp+++/T3H7pNHE1atXq0SJEvL09DSD/93Cw8NVokQJubq6KigoSLNmzTKX3bp1S3369JGfn59cXV0VGBioCRMmmMtHjhyp/Pnzy8XFRf7+/urbt2+6z8fIkSNVrlw5zZ8/X4GBgfLx8VG7du109epVSXfuDti0aZNmzJhh3iGQdB7279+vRo0aydPTU3ny5FGnTp10/vz5dPd97+3lW7ZsUbly5eTq6qqKFStq2bJlstlsio6ONte5X58hISHq27evBg8erOzZs8vX11cjR4606/fSpUt67bXXlCdPHrm6uqp06dJasWKFXR01a9aUm5ubAgIC1LdvX12/fv2+xzNv3jx17NhRHTt21Lx581I83rlz56ply5Zyd3dX0aJFtXz5cnN5QkKCXn31VRUsWFBubm4qXry4ZsyYkWp/n376qXLkyKGbN2/atb/00kvq3LmzJGn37t2qXbu2vLy85O3treeee047duzQxo0b1bVrV12+fNn8ud57ngAAAAA8fTI9dN/t2rVrWrBggYoUKaIcOXKke7vevXvr5s2b+uGHH7R3715NmjRJnp6eqa5/48YNTZ06VfPnz9cPP/ygEydOaNCgQebyOXPmaOjQoRo3bpxiYmI0fvx4DRs2TJGRkZKkmTNnavny5VqyZIkOHDigzz77TIGBgZKkL7/8Uu+9954++eQTHTp0SMuWLVOZMmUe6DwcOXJEy5Yt04oVK7RixQpt2rRJEydOlCTNmDFDVatWVY8ePcw7BAICAhQXF6datWqpXLly2rFjh1atWqUzZ86oTZs2D9R3kqtXr6pp06YqU6aMdu3apTFjxujtt9+2Wye9fUZGRsrDw0Pbtm3T5MmTNXr0aK1du1aSlJiYqIYNG2rLli367LPPtH//fk2cOFFZsmSRJO3du1f169dXq1attGfPHi1evFg//fST+vTpc99zuHXrVrVp00Zt2rTRli1bdPTo0WTrjRo1Sm3atNGePXvUqFEjdejQQRcvXjRry5cvn5YsWaL9+/dr+PDhevfdd7VkyZIU+2zdurUSEhLsgvv58+e1YsUKde3aVZLUoUMH5cuXT1FRUdq5c6feeecdOTk5qVq1anr//ffl7e1t/lzvviaT3Lx5U1euXLF7AQAAAHhyOWZ2AStWrDAD8vXr1+Xn56cVK1bIwSH9nwecOHFCL730khluCxUqlOb6t2/f1uzZs1W4cGFJUp8+fTR69Ghz+ZgxYzRt2jS1atVKklSwYEHt379fn3zyibp06aITJ06oaNGi+te//iWbzaYCBQrY1eLr66u6devKyclJ+fPnV+XKldN9LNKdsBcRESEvLy9JUqdOnbRu3TqNGzdOPj4+cnZ2lru7u3x9fc1tPv74Y1WoUEHjx48328LCwhQQEKCDBw+qWLFiD1TDggULZLPZNGfOHLm6uqpkyZI6deqUevTo8cB9BgcHa8SIEZKkokWL6sMPP9S6detUr149/e9//9P27dsVExNjrn/3z2/KlCl65ZVXzGfYixYtqpkzZ6pWrVr6+OOP5erqmmL9YWFhatiwobJlyybpzmMMYWFhGjt2rN16oaGhat++vSRp/Pjx+uCDD7R9+3Y1aNBATk5OGjVqlLluwYIFtWXLFi1ZsiTFDzPc3Nz0yiuvKDw8XK1btzbPY758+RQSEiLpzvXx73//W0FBQebxJPHx8ZHNZrP7ud5rwoQJdjUBAAAAeLJl+kh37dq1FR0drejoaG3btk0vvviiGjZsqOPHj6d7H3379tXYsWNVvXp1jRgx4r4Tsbm7u5uBW5L8/Px09uxZSdK5c+d08uRJvfrqq/L09DRfY8eO1ZEjRyTdCWrR0dEqXry4+vbtqzVr1pj7at26tf766y8VKlRIPXr00Ndff634+PgHOSUKDAw0A/e99aVm586d2rBhg13NScEuqe4HceDAAQUHB9uF2ns/PEhvn8HBwXbb3X080dHRypcvX6ofCuzcuVMRERF2fdSvX1+JiYk6duxYitskJCQoMjJSHTt2NNs6duyoyMhIJSQk2K17d20eHh7y8vKyO9ezZ89WxYoVlStXLnl6emrOnDk6ceJEiv1KUo8ePbRmzRqdOnVK0p3HFJImDJSkgQMHqnv37qpbt64mTpz4wD+bIUOG6PLly+br5MmTD7Q9AAAAgMcr00e6PTw8VKRIEfP9c889Jx8fH82ZM0djx441R7wNwzDXuX37tt0+unfvrvr16+u7777TmjVrNGHCBE2bNk1vvvlmin06OTnZvbfZbOb+ExMTJd25xbxKlSp26yXd8lyhQgUdO3ZMK1eu1P/+9z+1adNGdevW1ZdffqmAgAAdOHBAa9eu1f/+9z/16tVLU6ZM0aZNm5L1m5qU6kuqKzWJiYlq2rSpJk2alGyZn59fuvq9m2EYySafu/tn8CB9pnU8bm5uadaRmJio119/PcXn4vPnz5/iNqtXr9apU6fUtm1bu/aEhAStWbPGbob2tGpbsmSJBgwYoGnTpqlq1ary8vLSlClTtG3btlTrLV++vMqWLatPP/1U9evX1969e/Xtt9+ay0eOHKlXXnlF3333nVauXKkRI0Zo0aJFatmyZZrnIYmLi8szNdkdAAAA8KzL9NB9L5vNJgcHB/MrnnLlyiXpzvPDSbcK3z2RV5KAgAD17NlTPXv21JAhQzRnzpxUQ3da8uTJo7x58+ro0aPq0KFDqut5e3urbdu2atu2rV5++WU1aNBAFy9eVPbs2eXm5qZmzZqpWbNm6t27t4KCgrR3715VqFDhgetJibOzc7IR2woVKuirr75SYGCgHB0f/ccaFBSkBQsW6ObNm2bI27FjR4b3GRwcrN9//z3VW+ArVKigX3/91e6DmfuZN2+e2rVrp6FDh9q1T5w4UfPmzUv316L9+OOPqlatmnr16mW2pWdkunv37nrvvfd06tQp1a1bVwEBAXbLixUrpmLFimnAgAFq3769wsPD1bJlyxR/rgAAAACebpl+e/nNmzd1+vRpnT59WjExMXrzzTd17do1NW3aVJJUpEgRBQQEaOTIkTp48KC+++47TZs2zW4f/fv31+rVq3Xs2DHt2rVL69evV4kSJR66ppEjR2rChAmaMWOGDh48qL179yo8PFzTp0+XJL333ntatGiRfvvtNx08eFBffPGFfH19lTVrVkVERGjevHnat2+fjh49qvnz58vNzc3uue9HFRgYqG3btik2Nlbnz59XYmKievfurYsXL6p9+/bavn27jh49qjVr1qhbt24PFeReeeUVJSYm6rXXXlNMTIxWr16tqVOnSpI5Ap4RfdaqVUs1a9bUSy+9pLVr15p3EKxatUqS9Pbbb2vr1q3q3bu3oqOjdejQIS1fvjzVD1TOnTunb7/9Vl26dFHp0qXtXl26dNHy5cvNmfHvp0iRItqxY4dWr16tgwcPatiwYYqKirrvdh06dNCpU6c0Z84cdevWzWz/66+/1KdPH23cuFHHjx/X5s2bFRUVZV6rgYGBunbtmtatW6fz58/rxo0b6aoTAAAAwJMr00P3qlWr5OfnJz8/P1WpUkVRUVH64osvzImnnJyc9Pnnn+u3335T2bJlNWnSpGSTYSUkJKh3794qUaKEGjRooOLFi9t9xdeD6t69u+bOnauIiAiVKVNGtWrVUkREhAoWLChJ8vT01KRJk1SxYkVVqlRJsbGx+v777+Xg4KCsWbNqzpw5ql69uoKDg7Vu3Tp9++23DzQb+/0MGjRIWbJkUcmSJZUrVy6dOHFC/v7+2rx5sxISElS/fn2VLl1a/fr1k4+PzwNNSpfE29tb3377raKjo1WuXDkNHTpUw4cPlyTzOe+M6vOrr75SpUqV1L59e5UsWVKDBw82Q3twcLA2bdqkQ4cOqUaNGipfvryGDRuW6i3zn376qTw8PPTCCy8kW5b0VV3z589PV109e/ZUq1at1LZtW1WpUkUXLlywG/VOjbe3t1566SV5enqqRYsWZnuWLFl04cIFde7cWcWKFVObNm3UsGFDc2K0atWqqWfPnmrbtq1y5cqlyZMnp6tOAAAAAE8um3Hvg7pAKhYsWGB+l/T9nsX+p6tXr55KlCihmTNnWtrPlStX5OPjo4D+S+Tg4m5pXwDwJIqd2DizSwAA/EMl/S1++fJleXt7p7reE/dMN54cn376qQoVKqS8efNq9+7devvtt9WmTRsCdxouXryoNWvWaP369frwww8zuxwAAAAAmYzQjVSdPn1aw4cP1+nTp+Xn56fWrVtr3LhxmV3WE61ChQr6888/NWnSJBUvXjyzywEAAACQybi9HHiKcXs5gH86bi8HAGSW9N5enukTqQEAAAAA8KwidAMAAAAAYBFCNwAAAAAAFiF0AwAAAABgEUI3AAAAAAAWIXQDAAAAAGARQjcAAAAAABYhdAMAAAAAYBFCNwAAAAAAFiF0AwAAAABgEUI3AAAAAAAWIXQDAAAAAGARQjcAAAAAABYhdAMAAAAAYBFCNwAAAAAAFiF0AwAAAABgEUI3AAAAAAAWIXQDAAAAAGARQjcAAAAAABYhdAMAAAAAYBFCNwAAAAAAFiF0AwAAAABgEUI3AAAAAAAWIXQDAAAAAGARQjcAAAAAABYhdAMAAAAAYBFCNwAAAAAAFiF0AwAAAABgEUI3AAAAAAAWcczsAgA8un2j6svb2zuzywAAAABwD0a6AQAAAACwCKEbAAAAAACLELoBAAAAALAIoRsAAAAAAIsQugEAAAAAsAihGwAAAAAAixC6AQAAAACwCKEbAAAAAACLELoBAAAAALAIoRsAAAAAAIsQugEAAAAAsAihGwAAAAAAixC6AQAAAACwCKEbAAAAAACLELoBAAAAALAIoRsAAAAAAIsQugEAAAAAsAihGwAAAAAAixC6AQAAAACwCKEbAAAAAACLELoBAAAAALCIY2YXAODhGYYhSbpy5UomVwIAAAD8syT9DZ70N3lqCN3AU+zChQuSpICAgEyuBAAAAPhnunr1qnx8fFJdTugGnmLZs2eXJJ04cSLNX3TgUVy5ckUBAQE6efKkvL29M7scPKO4zvA4cJ3hceA6++cwDENXr16Vv79/musRuoGnmIPDnWkZfHx8+EcdlvP29uY6g+W4zvA4cJ3hceA6+2dIz8AXE6kBAAAAAGARQjcAAAAAABYhdANPMRcXF40YMUIuLi6ZXQqeYVxneBy4zvA4cJ3hceA6w71sxv3mNwcAAAAAAA+FkW4AAAAAACxC6AYAAAAAwCKEbgAAAAAALELoBp5is2bNUsGCBeXq6qrnnntOP/74Y2aXhKfYDz/8oKZNm8rf3182m03Lli2zW24YhkaOHCl/f3+5ubkpJCREv/76a+YUi6fShAkTVKlSJXl5eSl37txq0aKFDhw4YLcO1xke1ccff6zg4GDzO5KrVq2qlStXmsu5xmCFCRMmyGazqX///mYb1xqSELqBp9TixYvVv39/DR06VL/88otq1Kihhg0b6sSJE5ldGp5S169fV9myZfXhhx+muHzy5MmaPn26PvzwQ0VFRcnX11f16tXT1atXH3OleFpt2rRJvXv31s8//6y1a9cqPj5eL774oq5fv26uw3WGR5UvXz5NnDhRO3bs0I4dO1SnTh01b97cDDtcY8hoUVFR+u9//6vg4GC7dq41mAwAT6XKlSsbPXv2tGsLCgoy3nnnnUyqCM8SScbXX39tvk9MTDR8fX2NiRMnmm1///234ePjY8yePTsTKsSz4OzZs4YkY9OmTYZhcJ3BOtmyZTPmzp3LNYYMd/XqVaNo0aLG2rVrjVq1ahn9+vUzDIN/z2CPkW7gKXTr1i3t3LlTL774ol37iy++qC1btmRSVXiWHTt2TKdPn7a75lxcXFSrVi2uOTy0y5cvS5KyZ88uiesMGS8hIUGLFi3S9evXVbVqVa4xZLjevXurcePGqlu3rl071xru5pjZBQB4cOfPn1dCQoLy5Mlj154nTx6dPn06k6rCsyzpukrpmjt+/HhmlISnnGEYGjhwoP71r3+pdOnSkrjOkHH27t2rqlWr6u+//5anp6e+/vprlSxZ0gw7XGPICIsWLdKuXbsUFRWVbBn/nuFuhG7gKWaz2ezeG4aRrA3ISFxzyCh9+vTRnj179NNPPyVbxnWGR1W8eHFFR0fr0qVL+uqrr9SlSxdt2rTJXM41hkd18uRJ9evXT2vWrJGrq2uq63GtQWIiNeCplDNnTmXJkiXZqPbZs2eTfaIKZARfX19J4ppDhnjzzTe1fPlybdiwQfny5TPbuc6QUZydnVWkSBFVrFhREyZMUNmyZTVjxgyuMWSYnTt36uzZs3ruuefk6OgoR0dHbdq0STNnzpSjo6N5PXGtQSJ0A08lZ2dnPffcc1q7dq1d+9q1a1WtWrVMqgrPsoIFC8rX19fumrt165Y2bdrENYd0MwxDffr00dKlS7V+/XoVLFjQbjnXGaxiGIZu3rzJNYYM88ILL2jv3r2Kjo42XxUrVlSHDh0UHR2tQoUKca3BxO3lwFNq4MCB6tSpkypWrKiqVavqv//9r06cOKGePXtmdml4Sl27dk2HDx823x87dkzR0dHKnj278ufPr/79+2v8+PEqWrSoihYtqvHjx8vd3V2vvPJKJlaNp0nv3r21cOFCffPNN/Ly8jJHgHx8fOTm5mZ+xy3XGR7Fu+++q4YNGyogIEBXr17VokWLtHHjRq1atYprDBnGy8vLnI8iiYeHh3LkyGG2c60hCaEbeEq1bdtWFy5c0OjRoxUXF6fSpUvr+++/V4ECBTK7NDylduzYodq1a5vvBw4cKEnq0qWLIiIiNHjwYP3111/q1auX/vzzT1WpUkVr1qyRl5dXZpWMp8zHH38sSQoJCbFrDw8PV2hoqCRxneGRnTlzRp06dVJcXJx8fHwUHBysVatWqV69epK4xvD4cK0hic0wDCOziwAAAAAA4FnEM90AAAAAAFiE0A0AAAAAgEUI3QAAAAAAWITQDQAAAACARQjdAAAAAABYhNANAAAAAIBFCN0AAAAAAFiE0A0AAAAAgEUI3QAAAHgoFy5cUO7cuRUbG/vQ+zh79qxy5cqlU6dOZVxhAPAEIXQDAIDHJjQ0VDabTTabTU5OTipUqJAGDRqk69evP9J+R44cqXLlyj227azyyy+/qEmTJsqdO7dcXV0VGBiotm3b6vz585ldWoomTJigpk2bKjAwUJJ08eJFNW3aVJ6enqpQoYJ2795tt36vXr00bdo0u7bcuXOrU6dOGjFixOMqGwAeK0I3AAB4rBo0aKC4uDgdPXpUY8eO1axZszRo0KAU1719+/Zjri7znD17VnXr1lXOnDm1evVqxcTEKCwsTH5+frpx44Zl/T7sOf7rr780b948de/e3WwbN26crl69ql27dqlWrVp2y7Zu3art27erf//+yfbVtWtXLViwQH/++edD1QIATzJCNwAAeKxcXFzk6+urgIAAvfLKK+rQoYOWLVsm6f9GnsPCwlSoUCG5uLjIMAydOHFCzZs3l6enp7y9vdWmTRudOXNGkhQREaFRo0Zp9+7d5ih6RESEJD3Udt26dVOTJk3sao6Pj5evr6/CwsIkSSEhIerTp4/69OmjrFmzKkeOHPrPf/4jwzDMbW7duqXBgwcrb9688vDwUJUqVbRx48ZUz8uWLVt05coVzZ07V+XLl1fBggVVp04dvf/++8qfP7+53q+//qrGjRvL29tbXl5eqlGjho4cOSJJSkxM1OjRo5UvXz65uLioXLlyWrVqlbltbGysbDablixZopCQELm6uuqzzz6TJIWHh6tEiRJydXVVUFCQZs2alebPceXKlXJ0dFTVqlXNtpiYGLVr107FihXTa6+9pv3790u6E+zfeOMNzZ49W1myZEm2rzJlysjX11dff/11mn0CwNOI0A0AADKVm5ub3Wjr4cOHtWTJEn311VeKjo6WJLVo0UIXL17Upk2btHbtWh05ckRt27aVJLVt21ZvvfWWSpUqpbi4OMXFxalt27YyDOOhtuvevbtWrVqluLg4s6bvv/9e165dU5s2bcy2yMhIOTo6atu2bZo5c6bee+89zZ0711zetWtXbd68WYsWLdKePXvUunVrNWjQQIcOHUrxPPj6+io+Pl5ff/21XXi/26lTp1SzZk25urpq/fr12rlzp7p166b4+HhJ0owZMzRt2jRNnTpVe/bsUf369dWsWbNkfb799tvq27evYmJiVL9+fc2ZM0dDhw7VuHHjFBMTo/Hjx2vYsGGKjIxM9ef2ww8/qGLFinZtZcuW1fr16xUfH6/Vq1crODhYkjRp0iSFhIQkW/9ulStX1o8//pjqcgB4ahkAAACPSZcuXYzmzZub77dt22bkyJHDaNOmjWEYhjFixAjDycnJOHv2rLnOmjVrjCxZshgnTpww23799VdDkrF9+3Zzu7Jly9r19bDbGYZhlCxZ0pg0aZL5vkWLFkZoaKj5vlatWkaJEiWMxMREs+3tt982SpQoYRiGYRw+fNiw2WzGqVOn7Pb7wgsvGEOGDEn1/Lz77ruGo6OjkT17dqNBgwbG5MmTjdOnT5vLhwwZYhQsWNC4detWitv7+/sb48aNs2urVKmS0atXL8MwDOPYsWOGJOP999+3WycgIMBYuHChXduYMWOMqlWrplpr8+bNjW7dutm1Xbp0yWjfvr2RP39+o2bNmsavv/5qHDx40ChatKhx/vx54/XXXzcKFixotG7d2rh06ZLdtgMGDDBCQkJS7Q8AnlaMdAMAgMdqxYoV8vT0lKurq6pWraqaNWvqgw8+MJcXKFBAuXLlMt/HxMQoICBAAQEBZlvJkiWVNWtWxcTEpNrPw24nSd27d1d4eLikO89af/fdd+rWrZvdOs8//7xsNpv5vmrVqjp06JASEhK0a9cuGYahYsWKydPT03xt2rTJvBU8JePGjdPp06c1e/ZslSxZUrNnz1ZQUJD27t0rSYqOjlaNGjXk5OSUbNsrV67ojz/+UPXq1e3aq1evnux47x5xPnfunE6ePKlXX33VrtaxY8emWetff/0lV1dXuzYfHx8tXLhQx48f16ZNm1SyZEm9/vrrmjJlihYsWKCjR4/qwIEDcnd31+jRo+22dXNzs/TZdQDILI6ZXQAAAPhnqV27tj7++GM5OTnJ398/WYD08PCwe28Yhl24vV/7o24nSZ07d9Y777yjrVu3auvWrQoMDFSNGjXS3OZuiYmJypIli3bu3JnsGWZPT880t82RI4dat26t1q1ba8KECSpfvrymTp2qyMhIubm53bfve48tpeO9+xwnJiZKkubMmaMqVarYrZfS89dJcubMed+Jz8LCwpQ1a1Y1b95crVq1UosWLeTk5KTWrVtr+PDhdutevHjR7sMWAHhWELoBAMBj5eHhoSJFiqR7/ZIlS+rEiRM6efKkOWq9f/9+Xb58WSVKlJAkOTs7KyEhIUO2k+4E3xYtWig8PFxbt25V165dk63z888/J3tftGhRZcmSReXLl1dCQoLOnj37QGH9Xs7OzipcuLD5lWrBwcGKjIzU7du3k31Y4e3tLX9/f/3000+qWbOm2b5lyxZVrlw51T7y5MmjvHnz6ujRo+rQoUO6aytfvrw5CVtKzp07pzFjxuinn36SJCUkJJjP7t++fTvZed+3b59CQkLS3T8APC24vRwAADzR6tatq+DgYHXo0EG7du3S9u3b1blzZ9WqVcu8TTowMFDHjh1TdHS0zp8/r5s3bz70dkm6d++uyMhIxcTEqEuXLsnqOnnypAYOHKgDBw7o888/1wcffKB+/fpJkooVK6YOHTqoc+fOWrp0qY4dO6aoqChNmjRJ33//fYrHuWLFCnXs2FErVqzQwYMHdeDAAU2dOlXff/+9mjdvLknq06ePrly5onbt2mnHjh06dOiQ5s+frwMHDkiS/v3vf2vSpElavHixDhw4oHfeeUfR0dFmXakZOXKkJkyYoBkzZujgwYPau3evwsPDNX369FS3qV+/vn799ddUR7v79eunt956S3nz5pV05zb3+fPnKyYmRv/973/tboO/ceOGdu7cqRdffDHNOgHgqZSZD5QDAIB/lnsnUrtXahObHT9+3GjWrJnh4eFheHl5Ga1bt7abYOzvv/82XnrpJSNr1qyGJCM8PPyRtjMMw0hMTDQKFChgNGrUKFk9tWrVMnr16mX07NnT8Pb2NrJly2a88847dhOr3bp1yxg+fLgRGBhoODk5Gb6+vkbLli2NPXv2pHjsR44cMXr06GEUK1bMcHNzM7JmzWpUqlTJribDMIzdu3cbL774ouHu7m54eXkZNWrUMI4cOWIYhmEkJCQYo0aNMvLmzWs4OTkZZcuWNVauXGlumzSR2i+//JKs/wULFhjlypUznJ2djWzZshk1a9Y0li5dmmKtSZ5//nlj9uzZydpXrVplVK5c2UhISDDbrl+/brRu3drw8vIyXnjhBePMmTPmsoULFxrFixdPsy8AeFrZDCOV76QAAAD4B7tx44b8/f0VFhamVq1a2S0LCQlRuXLl9P7772dOcU+I77//XoMGDdK+ffvk4PDwN1BWrlxZ/fv31yuvvJKB1QHAk4FnugEAAO6SmJio06dPa9q0afLx8VGzZs0yu6QnVqNGjXTo0CGdOnXKbpb4B3H27Fm9/PLLat++fQZXBwBPBkI3AADAXU6cOKGCBQsqX758ioiIkKMjfy6l5X7Pi99P7ty5NXjw4AyqBgCePNxeDgAAAACARZi9HAAAAAAAixC6AQAAAACwCKEbAAAAAACLELoBAAAAALAIoRsAAAAAAIsQugEAAAAAsAihGwAAAAAAixC6AQAAAACwCKEbAAAAAACL/D+49Hf9UUjkjQAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Chart saved to ../outputs/prototype_results_chart.png\n" + ] + } + ], + "source": [ + "plt.figure(figsize=(10, 6))\n", + "plt.barh(final_results[\"title\"], final_results[\"prototype_score\"])\n", + "plt.xlabel(\"Prototype Score (%)\")\n", + "plt.ylabel(\"Job Title\")\n", + "plt.title(\"Resume-to-Job Matching Prototype Results\")\n", + "plt.gca().invert_yaxis()\n", + "plt.tight_layout()\n", + "plt.savefig(\"../outputs/prototype_results_chart.png\")\n", + "plt.show()\n", + "\n", + "print(\"Chart saved to ../outputs/prototype_results_chart.png\")" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "abca933d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Saved: ../outputs/ranked_jobs.csv\n", + "Saved: ../outputs/final_prototype_results.csv\n" + ] + } + ], + "source": [ + "ranked_jobs.to_csv(\"../outputs/ranked_jobs.csv\", index=False)\n", + "final_results.to_csv(\"../outputs/final_prototype_results.csv\", index=False)\n", + "print(\"Saved: ../outputs/ranked_jobs.csv\")\n", + "print(\"Saved: ../outputs/final_prototype_results.csv\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From f181879008cc4e9942a0e4aad72a8c0cf64bad9d Mon Sep 17 00:00:00 2001 From: Basil Behanan <158139580+Basilbe@users.noreply.github.com> Date: Sat, 4 Apr 2026 19:34:15 +1100 Subject: [PATCH 07/13] Delete Playground/Basil/notebooks/temp --- Playground/Basil/notebooks/temp | 1 - 1 file changed, 1 deletion(-) delete mode 100644 Playground/Basil/notebooks/temp diff --git a/Playground/Basil/notebooks/temp b/Playground/Basil/notebooks/temp deleted file mode 100644 index 8b13789179..0000000000 --- a/Playground/Basil/notebooks/temp +++ /dev/null @@ -1 +0,0 @@ - From 206b768e4b8f0da35edcddc25c30c98247a307a7 Mon Sep 17 00:00:00 2001 From: Basil Behanan <158139580+Basilbe@users.noreply.github.com> Date: Sat, 4 Apr 2026 19:34:32 +1100 Subject: [PATCH 08/13] Add files via upload --- Playground/Basil/data/jobs.csv | 6 +++ Playground/Basil/data/resume.txt | 85 ++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 Playground/Basil/data/jobs.csv create mode 100644 Playground/Basil/data/resume.txt diff --git a/Playground/Basil/data/jobs.csv b/Playground/Basil/data/jobs.csv new file mode 100644 index 0000000000..96dc2e817b --- /dev/null +++ b/Playground/Basil/data/jobs.csv @@ -0,0 +1,6 @@ +job_id,title,company,description +1,Data Analyst,Company A,"Looking for a candidate with experience in Python, SQL, dashboards, reporting, and data visualization. Knowledge of Tableau or Power BI is preferred." +2,Junior Data Scientist,Company B,"Seeking a graduate with experience in machine learning, Python, data preprocessing, feature engineering, and model evaluation." +3,Machine Learning Intern,Company C,"The ideal applicant has worked on machine learning projects, computer vision tasks, Python programming, and model training workflows." +4,AI Engineer Intern,Company D,"Looking for students with exposure to deep learning, NLP, Python, data pipelines, and practical AI project experience." +5,Business Intelligence Analyst,Company E,"Candidates should have knowledge of SQL, reporting, dashboard creation, Power BI, Excel, and stakeholder communication." \ No newline at end of file diff --git a/Playground/Basil/data/resume.txt b/Playground/Basil/data/resume.txt new file mode 100644 index 0000000000..2516fe9b32 --- /dev/null +++ b/Playground/Basil/data/resume.txt @@ -0,0 +1,85 @@ +Basil Behanan +Tel: +61 468410310 +Email: Basilbehanan5@gmail.com +LinkedIn: LinkedIn + +Career Profile +Final-year Computer Science student majoring in Data Science with experience applying data analytics, machine learning, and data engineering techniques to solve complex problems. Skilled in extracting, transforming, and analysing large datasets using Python, SQL, and statistical modelling tools to generate actionable insights. Experienced working in collaborative technical teams to develop analytical solutions, improve data workflows, and communicate technical findings to technical and non-technical stakeholders. +Key Skills +Programming & Analytics +Python, SQL, R, C++, C#, Excel, Power BI +Data Science & Machine Learning +TensorFlow, Scikit-learn, OpenCV, statistical modelling, feature engineering, model evaluation +Data Engineering & Infrastructure +ETL workflows, Docker, Git, GitHub Actions (CI/CD), Google Cloud Storage, AWS S3, Kubernetes +Data Systems & Visualisation +Power BI, MySQL, Jupyter Lab, Excel analytics +Concepts +Data lifecycle management, distributed computing, machine learning pipelines, data quality validation, reproducible experimentation + +Education + +Deakin University Burwood, VIC +Bachelor of Computer Science Graduation Date: June 2026 +Major: Data Science +Achievements: Above 75 WAM +Relevant Coursework: Intro to Data Science and AI, Machine Learning, Database Fundamentals, Linear Algebra for Data Analysis, Discrete Mathematics, Data Wrangling, Applied Algebra and Statistics + + + + + + + + + +Professional Experience + +Superstat Richmond, VIC +Computer Vision and Sports Analytics Intern Jul 2025 – Sep 2025 +• Prepared and validated over 2,000 annotated AFL video frames to support machine learning model development and analytical workflows. +• Contributed to computer vision classification and OCR pipelines achieving ~90% and ~95% accuracy respectively. +• Implemented CI/CD workflows using GitHub Actions, automating testing, dependency installation, and validation checks for machine learning experiments. +• Standardised development environments using Docker, improving reproducibility across machine learning experimentation. +• Utilised AWS S3 for dataset storage and cloud-based experimentation workflows. +• Collaborated closely with machine learning engineers to evaluate models and refine data preparation and validation processes. +Leadership Experience + +RedBack Operations - Project Orion (Sports AI Pipeline) Burwood, VIC +Team Lead – Sports Analytics & Annotation Jul 2025 – Sep 2025 +• Led a team of five analysts to build a scalable annotation pipeline supporting machine learning training across 10,000+ video frames. +• Designed structured data schemas and quality-control processes, improving dataset reliability by 30%+. +• Managed dataset storage and access workflows using Google Cloud Storage to support distributed team collaboration. +• Implemented Git-based version control workflows, coordinating dataset and code updates across teams through GitHub repositories. +• Collaborated cross-functionally with engineering and analytics teams to ensure datasets aligned with model validation requirements. +• Produced documentation and onboarding guides to streamline contributor onboarding and workflow consistency. +Project Experience + +Distributed Recommendation System (Parallel ML Processing) +• Built distributed Python-based recommendation engine using MPI, reducing execution time by 38%. +• Designed scalable preprocessing workflows and evaluation pipelines. +• Applied collaborative and content-based filtering techniques. +Financial Data Analysis - Cryptocurrency Market Study +• Performed exploratory data analysis on Bitcoin market data using Python (NumPy, Matplotlib) to analyse volatility trends and trading behaviour. +• Generated statistical summaries and visualisations to interpret financial data patterns and market fluctuations + + +Health Data Analytics - BMI Population Analysis +• Analysed NHANES health datasets using Python and NumPy to study BMI distribution across population groups. +• Applied statistical analysis, correlation matrices, scatterplot analysis, and data visualisation techniques. +Machine Learning – IoT Cyber-Attack Classification +• Developed machine learning models to detect cyber-attacks within IoT networks using supervised learning techniques. +• Evaluated model performance using accuracy, precision, recall, and confusion matrix metrics. +Predictive Analytics – Heart Disease Prediction System +• Designed a machine learning pipeline combining feature selection, PCA dimensionality reduction, and ensemble learning models. +• Implemented models including Random Forest, Logistic Regression, and XGBoost for predictive health analytics. +Courses and Certificates + +• Data Analysis with python (freeCodeCamp) +• Intro to C++ (LCC Computer Education) + +Referees + + Available upon request + + From fbe00825e0300171a650b9fc797430a39b8152f1 Mon Sep 17 00:00:00 2001 From: Basil Behanan <158139580+Basilbe@users.noreply.github.com> Date: Sat, 4 Apr 2026 19:35:00 +1100 Subject: [PATCH 09/13] Add files via upload --- .../Basil/outputs/final_prototype_results.csv | 6 ++++++ .../Basil/outputs/prototype_results_chart.png | Bin 0 -> 28747 bytes Playground/Basil/outputs/ranked_jobs.csv | 6 ++++++ 3 files changed, 12 insertions(+) create mode 100644 Playground/Basil/outputs/final_prototype_results.csv create mode 100644 Playground/Basil/outputs/prototype_results_chart.png create mode 100644 Playground/Basil/outputs/ranked_jobs.csv diff --git a/Playground/Basil/outputs/final_prototype_results.csv b/Playground/Basil/outputs/final_prototype_results.csv new file mode 100644 index 0000000000..1a99829e78 --- /dev/null +++ b/Playground/Basil/outputs/final_prototype_results.csv @@ -0,0 +1,6 @@ +title,company,match_percentage,skill_overlap_score,prototype_score,matched_skills,missing_skills +Machine Learning Intern,Company C,22.43,100.0,45.7,"computer vision, machine learning, python",None +Junior Data Scientist,Company B,30.77,80.0,45.54,"feature engineering, machine learning, model evaluation, python",data preprocessing +AI Engineer Intern,Company D,18.68,33.33,23.07,python,"deep learning, nlp" +Data Analyst,Company A,12.12,42.86,21.34,"power bi, python, sql","dashboard, data visualization, reporting, tableau" +Business Intelligence Analyst,Company E,4.05,60.0,20.84,"excel, power bi, sql","dashboard, reporting" diff --git a/Playground/Basil/outputs/prototype_results_chart.png b/Playground/Basil/outputs/prototype_results_chart.png new file mode 100644 index 0000000000000000000000000000000000000000..11487875d6f291ff2b4211ab80dbe3bb5817010c GIT binary patch literal 28747 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 literal 0 HcmV?d00001 diff --git a/Playground/Basil/outputs/ranked_jobs.csv b/Playground/Basil/outputs/ranked_jobs.csv new file mode 100644 index 0000000000..f4fcdb1b91 --- /dev/null +++ b/Playground/Basil/outputs/ranked_jobs.csv @@ -0,0 +1,6 @@ +job_id,title,company,description,cleaned_description,similarity_score,match_percentage,job_skills,matched_skills,missing_skills,skill_overlap_score,prototype_score +3,Machine Learning Intern,Company C,"The ideal applicant has worked on machine learning projects, computer vision tasks, Python programming, and model training workflows.",ideal applicant worked machine learning projects computer vision tasks python programming model training workflows,0.22428559051351118,22.43,"['computer vision', 'machine learning', 'python']","['computer vision', 'machine learning', 'python']",[],100.0,45.7 +2,Junior Data Scientist,Company B,"Seeking a graduate with experience in machine learning, Python, data preprocessing, feature engineering, and model evaluation.",seeking graduate experience machine learning python data preprocessing feature engineering model evaluation,0.30770548309221246,30.77,"['data preprocessing', 'feature engineering', 'machine learning', 'model evaluation', 'python']","['feature engineering', 'machine learning', 'model evaluation', 'python']",['data preprocessing'],80.0,45.54 +4,AI Engineer Intern,Company D,"Looking for students with exposure to deep learning, NLP, Python, data pipelines, and practical AI project experience.",looking students exposure deep learning nlp python data pipelines practical ai project experience,0.18681678053158468,18.68,"['deep learning', 'nlp', 'python']",['python'],"['deep learning', 'nlp']",33.33,23.07 +1,Data Analyst,Company A,"Looking for a candidate with experience in Python, SQL, dashboards, reporting, and data visualization. Knowledge of Tableau or Power BI is preferred.",looking candidate experience python sql dashboards reporting data visualization knowledge tableau power bi preferred,0.12124111166261878,12.12,"['dashboard', 'data visualization', 'power bi', 'python', 'reporting', 'sql', 'tableau']","['power bi', 'python', 'sql']","['dashboard', 'data visualization', 'reporting', 'tableau']",42.86,21.34 +5,Business Intelligence Analyst,Company E,"Candidates should have knowledge of SQL, reporting, dashboard creation, Power BI, Excel, and stakeholder communication.",candidates knowledge sql reporting dashboard creation power bi excel stakeholder communication,0.04049510394504799,4.05,"['dashboard', 'excel', 'power bi', 'reporting', 'sql']","['excel', 'power bi', 'sql']","['dashboard', 'reporting']",60.0,20.84 From dcbaa1b4df09ca7e272eed1c2fdd79fb1ebd0163 Mon Sep 17 00:00:00 2001 From: Basil Behanan <158139580+Basilbe@users.noreply.github.com> Date: Sat, 4 Apr 2026 19:35:22 +1100 Subject: [PATCH 10/13] Delete Playground/Basil/outputs/temp --- Playground/Basil/outputs/temp | 1 - 1 file changed, 1 deletion(-) delete mode 100644 Playground/Basil/outputs/temp diff --git a/Playground/Basil/outputs/temp b/Playground/Basil/outputs/temp deleted file mode 100644 index 8b13789179..0000000000 --- a/Playground/Basil/outputs/temp +++ /dev/null @@ -1 +0,0 @@ - From 9798422463b7ee5926641c3b9b24a30edf1790ce Mon Sep 17 00:00:00 2001 From: Basil Behanan <158139580+Basilbe@users.noreply.github.com> Date: Sat, 4 Apr 2026 19:36:06 +1100 Subject: [PATCH 11/13] Create temp --- Playground/Basil/src/temp | 1 + 1 file changed, 1 insertion(+) create mode 100644 Playground/Basil/src/temp diff --git a/Playground/Basil/src/temp b/Playground/Basil/src/temp new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/Playground/Basil/src/temp @@ -0,0 +1 @@ + From 716c9d380eac6028971d7b1c24b249bae69a257d Mon Sep 17 00:00:00 2001 From: Basil Behanan <158139580+Basilbe@users.noreply.github.com> Date: Sat, 4 Apr 2026 19:36:20 +1100 Subject: [PATCH 12/13] Delete Playground/Basil/src/temp --- Playground/Basil/src/temp | 1 - 1 file changed, 1 deletion(-) delete mode 100644 Playground/Basil/src/temp diff --git a/Playground/Basil/src/temp b/Playground/Basil/src/temp deleted file mode 100644 index 8b13789179..0000000000 --- a/Playground/Basil/src/temp +++ /dev/null @@ -1 +0,0 @@ - From 57e7a1ee1b0a0fe4e06856e71a51b2408c2111c4 Mon Sep 17 00:00:00 2001 From: Basil Behanan <158139580+Basilbe@users.noreply.github.com> Date: Sat, 4 Apr 2026 19:37:18 +1100 Subject: [PATCH 13/13] Enhance README with project overview and instructions Added detailed project information, including structure, workflow, requirements, and matching logic. --- Playground/Basil/Readme.md | 86 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/Playground/Basil/Readme.md b/Playground/Basil/Readme.md index 8b13789179..124d5d99a7 100644 --- a/Playground/Basil/Readme.md +++ b/Playground/Basil/Readme.md @@ -1 +1,87 @@ +# Resume Job Matcher + +A notebook-based prototype that ranks job postings against a resume using a combination of text similarity and skill overlap. + +## What It Does + +This project compares a resume with a set of job descriptions and produces ranked matches. It uses two signals: + +- TF-IDF + cosine similarity for overall text relevance +- Skill extraction and overlap for a more targeted match score + +The notebook then combines those scores into a final prototype score and exports the results. + +## Project Structure + +```text +resume_job_matcher/ +├── data/ +│ ├── jobs.csv +│ └── resume.txt +├── notebooks/ +│ └── resume_job_matching.ipynb +├── outputs/ +│ ├── final_prototype_results.csv +│ ├── ranked_jobs.csv +│ └── prototype_results_chart.png +├── src/ +└── requirements.txt +``` + +## Notebook Workflow + +The notebook is organized into clear sections: + +1. Imports and setup +2. Load input data +3. Text preprocessing +4. Text similarity matching +5. Skill extraction and overlap +6. Final scoring and ranking +7. Reporting, visualization, and export + +## Requirements + +Install the Python packages listed in `requirements.txt`. + +Typical dependencies include: + +- pandas +- nltk +- scikit-learn +- matplotlib + +## How to Run + +1. Open `notebooks/resume_job_matching.ipynb`. +2. Run the cells from top to bottom. +3. Make sure the data files are available in `data/`. +4. Review the ranked matches and generated outputs in `outputs/`. + +## Inputs + +- `data/resume.txt`: Plain-text resume used as the matching profile +- `data/jobs.csv`: Job postings dataset with job titles, companies, and descriptions + +## Outputs + +The notebook writes the following files to `outputs/`: + +- `ranked_jobs.csv`: Jobs ranked by similarity score +- `final_prototype_results.csv`: Final combined results with match and skill scores +- `prototype_results_chart.png`: Bar chart of final prototype scores + +## Matching Logic + +The ranking is based on a weighted score: + +- 70% text match score +- 30% skill overlap score + +This keeps the prototype simple while still reflecting both broad relevance and concrete skill alignment. + +## Notes + +- The notebook downloads the NLTK `punkt` and `stopwords` resources on first run. +- If you change the resume or job data, rerun the notebook from the top to refresh all outputs.