Back to Projects
PythonFlaskspaCyscikit-learnTF-IDFkNNrapidfuzzpandas

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.

Solo Developer
ChefMate

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.

ChefMate normalises free text before retrieval, and filters the candidate set before vectorising it.INPUT - FLASKIngredient Formcuisine / diet / meal filtersraw comma-separated textNORMALISATIONspaCy Lemmatiseren_core_web_smSynonym Mapregional name variantsrapidfuzz80% similarity floorclean canonical tokensCANDIDATE SELECTIONColumn Filterscuisine, diet, meal typeDeduplicateby recipe namereduced dataframeRETRIEVAL - PICKLED ARTEFACTTF-IDF Vectoriserfitted, persistedkNN Lookupkneighbors over candidatesranked neighboursOUTPUTScored Recipesmatched + missing + overlap %
ChefMate normalises free text before retrieval, and filters the candidate set before vectorising it.Scroll sideways to see the full diagram

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

1

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.

2

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

3
Pipeline Stages
Lemmatisation, synonym mapping, and fuzzy correction before any matching
80%
Fuzzy Threshold
Similarity floor below which a correction is rejected rather than guessed
Matched + missing
Result Detail
Every recipe shows both lists alongside its overlap score