ChefMate
Most recipe sites work backwards: pick a dish, then go shopping. ChefMate starts from the ingredients already on hand and finds the closest matches, showing what is missing for each so the trade-off is visible before committing to a dish.

The Problem
Free-text ingredient input breaks naive matching immediately. "Tomatoes", "tomato", and a typo like "tomatos" are three different strings, and regional names diverge further — aubergine and eggplant are the same vegetable. Exact matching fragments the search space and returns nothing useful.
The Solution
A normalisation stage runs before any matching. spaCy lemmatises each token to its base form, a hand-curated synonym map reconciles regional names, and rapidfuzz corrects remaining typos against the known ingredient vocabulary at an 80% similarity threshold. Only the cleaned tokens reach the retrieval step, so the model never sees the raw mess.
System Architecture
Cuisine, diet, and meal-type filters are applied to the dataframe first, which shrinks the candidate set before any vectorisation happens. The surviving recipes are transformed by a fitted TF-IDF vectoriser and queried with k-nearest-neighbours; the model, vectoriser, and dataframe are pickled together so a request only pays for lookup, not training.
Key Features
Innovative solutions developed to solve complex technical challenges.
Lemmatisation and synonym mapping
spaCy's en_core_web_sm reduces each ingredient to its lemma, then a curated map folds regional variants together — courgette to zucchini, garbanzo bean to chickpea, scallion to green onion.
Fuzzy correction against known vocabulary
rapidfuzz matches a mistyped ingredient to the closest term actually present in the dataset, accepting it only above an 80% similarity score so wrong corrections are rejected rather than guessed.
Filter-then-retrieve ordering
Cuisine, diet, and meal-type filters narrow the dataframe before vectorisation, so kNN searches a small relevant set instead of the whole corpus.
Transparent match scoring
Each result reports matched ingredients, missing ingredients, and a percentage computed from their overlap, so a low-ranked recipe explains itself.
Challenges & Breakthroughs
Challenge: The same ingredient arrives under many spellings, and exact matching treats each as unrelated.
Growth: Normalisation had to be a distinct pipeline stage rather than a helper sprinkled through the matching code. Once every input passed through one funnel — lemma, then synonym, then fuzzy — the retrieval logic got simpler because it could assume clean tokens.
Challenge: Fitting the vectoriser per request made responses slow enough to feel broken.
Growth: Pickled the trained model, the fitted vectoriser, and the recipe dataframe as one artefact loaded at predict time. Keeping them together matters more than it looks: a vectoriser separated from the data it was fitted on produces silently wrong vectors.
Results & Impact
Next Project
Integrated Healthcare Management System