Nutrient-aware food recommendation system built on USDA nutrient data. It learns food embeddings with a small autoencoder and ranks foods by similarity to a testosterone-supportive nutrient profile (protein, zinc, magnesium, selenium, B-vitamins) — not a claim that any individual food is medically proven to raise testosterone.
Given an activity level and (optionally) a food group, TestoAI returns a ranked list of foods that best match a nutrient profile built from seed foods known to be dense in the relevant micronutrients (e.g. oysters, egg yolk, beef liver). Ranking is rule-augmented: results are also shaped by activity-aware fat/calorie thresholds, food-group preferences, and filters that drop ultra-processed or near-duplicate items.
USDA nutrient data (Kaggle, or bundled sample fixture)
↓
preprocessing (column selection + MinMax scaling)
↓
autoencoder (13 → 64 → 16 → 64 → 13)
↓
food embeddings (16-dim, from the encoder)
↓
canonical recommender (cosine similarity to a seed-food prototype + rules)
↓
CLI / interactive demo
train.py builds the embeddings and saves them along with the encoder weights and scaler to data/ and model/. src/testoai/recommend.py loads those artifacts at inference time, scores every food by cosine similarity to the seed prototype, applies activity/food-group adjustments, and returns the top picks. demo.py and the testoai CLI both call this same function.
git clone <repo>
cd TestoAI
python -m pip install -e .
python train.py
python demo.pytrain.py first tries to download the full USDA National Nutrient Database via kagglehub (requires a Kaggle account/API token). If that's unavailable, it automatically falls back to the tracked sample fixture at fixtures/sample_nutrients.csv so training always succeeds — just with less food variety.
testoai --activity high --k 5
testoai --food-groups "Beef Products,Poultry Products" --activity medium--activity:low,medium/moderate, orhigh(defaultmoderate)--food-groups: comma-separated FoodGroup names to restrict results to (default: all groups)--k: cap the number of recommendations returned (default: full curated set)
--food-groups only affects which of these groups the recommender scores from — passing a FoodGroup outside this list returns no results:
Beef Products, Dairy and Egg Products, Fruits and Fruit Juices, Lamb, Veal, and Game Products, Finfish and Shellfish Products, Nut and Seed Products, Pork Products, Poultry Products
TestoAI/
├─ src/testoai/
│ ├─ recommend.py # canonical ranking/scoring engine
│ └─ cli.py # argument parsing, calls recommend()
├─ train.py # builds embeddings, saves artifacts to data/ and model/
├─ demo.py # interactive CLI demo
├─ fixtures/
│ └─ sample_nutrients.csv # tracked fallback dataset used when Kaggle is unavailable
├─ tests/ # pytest suite
├─ .github/workflows/ci.yml
├─ pyproject.toml
└─ README.md
data/ and model/ are generated by train.py and are gitignored.
pytestcovers the recommender (recommend()/load_embeddings()) and the CLI, using synthetic/fixture-derived artifacts — no Kaggle account or network access required.- GitHub Actions (
.github/workflows/ci.yml) runsruff checkandpyteston every push and pull request tomain.
Python, PyTorch (autoencoder), scikit-learn (scaling, cosine similarity), pandas/pyarrow (data + parquet artifacts), pytest, ruff.
evaluation/evaluate.py asks one question: does the learned autoencoder embedding provide anything useful compared with simpler nutrient-based baselines? There's no labeled ground truth for "correct" food recommendations, so this is a descriptive comparison of ranking behavior and nutrient composition, not an accuracy benchmark.
python evaluation/evaluate.py- Macro cosine baseline — cosine similarity to the mean normalized
Protein_g/Fat_g/Carb_gvector of the seed foods, using the fittedMinMaxScaler. - Raw normalized nutrient cosine — same approach, but using all 13 normalized nutrient columns from
model/meta.json(no autoencoder). - Autoencoder embedding cosine — same approach, using the learned 16-dim
emb_*embeddings. - Final rule-augmented TestoAI recommender — the real
recommend()used by the app/CLI, including activity thresholds, food-group weighting, and curation rules.
Methods 1-3 share the exact same seed foods (SEED_FOODS), candidate set, cosine-similarity method, and TOP_N=10; only the representation differs, so any difference between them is attributable to the representation itself. Method 4 is a system-level comparison, not a pure representation test — it intentionally adds rules on top of the embedding similarity.
Run against the full USDA dataset (6,894 rows):
| Method | Avg protein (g) | Avg sugar (g) | Avg fiber (g) | Avg calories | Food groups |
|---|---|---|---|---|---|
| Macro baseline | 21.9 | 1.7 | 0.9 | 253.6 | 8 |
| Raw nutrient baseline | 17.0 | 0.0 | 0.0 | 172.7 | 4 |
| Autoencoder embedding | 19.7 | 0.0 | 0.0 | 146.3 | 4 |
| Final TestoAI | 21.7 | 0.0 | 0.0 | 179.6 | 1 |
The key comparison is raw nutrient baseline vs. autoencoder embedding: full-candidate-ranking (Spearman-equivalent) correlation between the two is 0.87, but their top-10 lists overlap by only 2/10 (20%). See evaluation/results.csv for the full numbers, including macro-vs-embedding (0.85) and macro-vs-raw (0.95) correlations.
The raw nutrient and autoencoder rankings had a rank correlation of 0.87, indicating that the learned representation preserves much of the overall similarity structure already present in normalized nutrient space. Their top-10 recommendations overlapped by only 20%, however, showing that the embedding still meaningfully reorders which foods end up as the closest matches to the seed prototype. Without labeled ground truth, this evaluation can't establish whether that reordering is better, worse, or just different — only that it's a distinct ranking, not a restatement of the raw-nutrient one. The final recommender's top-10 was drawn entirely from Beef Products, which shows that in practice its output is influenced substantially by the explicit activity, food-group, and curation rules layered on top of similarity, not by the embedding alone.
- There is no labeled ground truth for "correct" recommendations — these metrics describe ranking behavior and nutrient composition, not recommendation accuracy or medical effectiveness.
- Results depend on the chosen seed foods (
SEED_FOODS) and nutrient features, and may look different with a different seed set. - The final recommender (method 4) is not a pure representation comparison, since it includes explicit activity/food-group rules on top of embedding similarity.
- Results generated from the bundled sample fixture (rather than the full USDA/Kaggle dataset) should not be interpreted as evidence of full-dataset model quality;
evaluate.pyprints the row count and warns when this may be the case. - Recommendations are heuristic/ranking-based, not medical advice.
MIT (see LICENSE).