jcousins/2026.04.002
NutriPlan
Personalised meal planning by vector retrieval over a curated database, with LLM optimisation against macro targets.
J. Cousins
Independent · London, UK
Keywords retrieval-augmented generation · pgvector · FastAPI · GPT-4o · iOS · nutrition science
1Introduction
Meal planning is a constrained optimisation problem dressed as a creative one. Users have explicit constraints (calorie targets, macro splits, allergies, time budget) and implicit constraints (taste, variety, cuisine preferences) that they cannot or will not articulate as rules. Most existing tools are template-based: a fixed catalogue of plans tweaked at the margins. We argue that the right architecture is to separate retrieval (which meals are plausible candidates given preferences and history) from optimisation (which subset of candidates best meets the day's targets), and to keep both surfaces narrow enough to test.
2Method
2.1Retrieval over generation
Pure GPT-4o generation tended to produce repeated meals across days within a week and was difficult to ground against accurate nutritional data. We instead retrieve approximately 100 candidate meals via pgvector cosine similarity (text-embedding-3-small, 1536 dimensions) over a curated meal database, then ask the LLM to optimise within that candidate set. The retrieval step also gives us a natural diversity knob: we constrain candidate selection by 14-day meal history.
2.2Two-model pipeline
Generation uses GPT-4o for quality. Feedback analysis (parsing free-text user responses into preference signals) uses GPT-4o-mini for cost efficiency. The two are abstracted behind LiteLLM so we can swap models per-task without touching application code. This was a small decision with a large compounding payoff: most of the cost optimisation in the system has come from picking the right model for the right step rather than from any prompt engineering.
2.3Preference embeddings
Rather than capturing preferences as explicit rules ("user dislikes mushrooms"), we update a per-user preference embedding from positive and negative meal feedback. This generalises across cuisines and ingredients in ways an explicit rule set does not. The trade-off is that the system is harder to introspect: "why was this meal suggested" becomes a vector-distance question rather than a rule-trace.
2.4Nutrition engine
Daily energy and macro targets are computed from the Henry/Oxford equations per UK SACN guidelines, supporting user-defined macro splits (e.g., 40% carbohydrate, 30% protein, 30% fat). The optimiser hits calorie targets within ±10% and macro splits with under 5% variance.
3Implementation
| Layer | Choice | Why |
|---|---|---|
| Client | Swift / SwiftUI · iOS 26 | Native performance, Liquid Glass design system. |
| Backend | FastAPI · async | High throughput, automatic OpenAPI, Pydantic validation. |
| DB | Supabase (Postgres 15) | Managed Postgres with pgvector, RLS for security. |
| Embeddings | text-embedding-3-small (1536d) | Cosine similarity for meal retrieval, low cost-per-call. |
| Generation | GPT-4o (meals), GPT-4o-mini (feedback) | Quality where it matters, cost efficiency where it does not. |
| Abstraction | LiteLLM | Swap models per-task without code changes. |
| Hosting | Render | Simple deploy from GitHub, env vars, free tier sufficient for MVP. |
4Results
- Calorie accuracy: within ±10% of target.
- Macro targeting: user-defined ratios with under 5% variance.
- End-to-end latency: under 2 seconds (retrieval + optimisation).
- API uptime: 99.8% on Render.
- Preference coverage: 100+ meals embedded into the user-feedback corpus.
5Discussion
The architectural call we keep returning to is the retrieval-then-optimise split. It is more code than a single LLM prompt, but it makes every other property of the system testable in isolation: nutrition targeting becomes deterministic, candidate diversity is a measurable quantity, and the LLM step is a small constraint-satisfaction problem rather than an open-ended generation task. We expect this pattern to generalise to other domains where the search space is finite and the optimisation surface is well-defined.
Near-term: complete the SwiftUI client and ship a TestFlight beta over summer 2026. Integrate Spoonacular and Edamam for richer recipe coverage. The product roadmap follows a freemium ladder: free calorie tracker, premium meal planning, pro for advanced personalisation and household coordination.
6References
- SACN, "Dietary Reference Values for Energy", UK Scientific Advisory Committee on Nutrition.
- Henry, C.J.K. (2005), "Basal metabolic rate studies in humans: measurement and development of new equations", Public Health Nutrition.
- Lewis, P. et al. (2020), "Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks", arXiv:2005.11401.