尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Whole-pack meal planner: LLM picks foods and grams, Python does packs, leftovers and macros
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗Whole-pack meal planner.
SmartBite turns one craving into one recipe in grams, a shopping list in whole packs, macros per serving and a plan for the leftovers. A language model picks the foods and the grams. Every number after that comes from code: pack sizes, leftovers, macros and estimated prices are plain Python with tests, built on open nutrition and pack data.
Live demo: https://smartbite-steel.vercel.app
Most meal planning apps write a plan first and send a list of generic food names to the store. The store then picks the products. Instacart's own API guide, for example, asks apps to send a generic product name with no weight, quantity or brand (Instacart docs). Once the product is chosen after the plan, the app cannot know the pack size you pay for or what is left over.
In real life you buy whole packs, and the grams in a recipe decide how many. Take canned tuna in 130 g cans for 7 servings: 93 g per serving is 651 g and buys a 6th can, while 92 g per serving fits in 5 cans. Among the meal apps reviewed for this project in October 2026, none was found that plans around packs like this (for two of them, Eat This Much and Prospre, no source covered it).
SmartBite does it the other way round:
flowchart LR
B["Browser<br/>(your own API key)"]
L["LLM provider<br/>picks foods and grams"]
E["Python engine on Vercel<br/>packs, leftovers, macros,<br/>estimated prices"]
B -- "craving, form, Kitchen Profile" --> L
L -- "4 ideas, then a recipe in grams" --> B
B -- "recipe (no API key)" --> E
E -- "meal result" --> B
The LLM picks foods and grams. All math is code.
smartbite_engine, served by FastAPI at /api/evaluate) maps each food to open nutrition values and typical pack sizes. It rounds up to whole packs and returns leftovers, macros per serving and, for Spain, an estimated price per pack (national, or for the user's comunidad autónoma).All numbers below are copied from the result files in eval/results/.
The 13 demo meals were computed twice: once by this engine with generic open tables (Ciqual 2025, USDA FoodData Central), and once by the author's personal app, which uses the labels of the products actually bought plus a national food table. The personal values are a reference, not ground truth. Error = (open - reference) / reference, per serving. Built on 2026-10-19 by eval/macro_compare.py and re-run on 2026-10-20 after fixes to the pack and nutrition data (full table).
| Meals | kcal mean abs error | kcal max error | kcal within 10% | protein mean abs error | protein max error | protein within 10% |
|---|---|---|---|---|---|---|
| 13 | 5.8% | 22.2% | 12 of 13 | 5.3% | 12.6% | 12 of 13 |
The one meal outside 10% on both is the tuna and chickpea salad with skyr dressing (kcal +22.2%, protein +12.6%).
15 golden cravings, 11 code checks each (165 checks): valid JSON, 4 ideas, idea names of 60 characters or less, the right number of servings, the recipe keeps the idea's main foods, no excluded food, rice and pasta in dry grams, eggs in units, grams for every ingredient, and macros inside the target range. The checks are code only. Replies for baseline and v2 were written on 2026-10-19. All three runs were re-scored on 2026-10-20 with the same checks, after the nutrition fix (baseline, v2, v3).
| Run | Checks passed | macros_vs_target |
|---|---|---|
| baseline | 153/165 (92.7%) | 3/15 |
| v2 | 164/165 (99.4%) | 14/15 |
| v3 | 165/165 (100.0%) | 15/15 |
The baseline first scored 152/165. One baseline recipe added a short top-level "note" that the recipe contract did not allow at the time. The contract now allows an optional note of up to 200 characters, so the same reply passes and all three runs are scored against the same contract.
What changed from baseline to v2 (from the project notes; the baseline prompt was not kept in the repo):
The one remaining miss is a turkey and sweet potato meal at 502 kcal against a 450 kcal target, after 3 attempts.
Caveat. The model replies in all three runs came from Claude Code subagents acting as the model, given the same prompts by hand (eval/run.py prompt). They were not calls to the production API from the web app. The scoring is the same code either way.
SmartBite runs on the user's own key, so the cost of a meal is its model calls: one for the 4 ideas, one for the recipe, and one more for each rerun.
Cost per meal, measured on Gemini. Live calls to the Gemini API through Google's OpenAI-compatible endpoint, the same route as the web app's experimental adapter, with two models. gemini-3.8-flash, the app's Gemini default until 2026-11-01, ran in seven runs from 2026-10-20 to 2026-10-27 (five of them produced meals) and finished 12 of the 15 golden cravings. The other 3 did not finish: the free tier answered with 503 (high demand) and 429 (quota exceeded) errors, or the connection failed. gemini-3.5-flash-lite, a cheaper model a user can type in the Model field, finished all 15 in one run on 2026-10-26, with 5 s between calls to stay under the free tier's 15 requests per minute (a first run without the gap hit that limit after 16 calls and is not used). The key was on the free tier, so nothing was billed. The costs below are estimated at Google's paid prices per million input and output tokens: $0.75 and $3.75 for 3.8 Flash (read 2026-10-19), $0.30 and $2.50 for 3.5 Flash-Lite (read 2026-10-26).
| Measure | 3.8 Flash, 12 meals | 3.5 Flash-Lite, 15 meals |
|---|---|---|
| Cost per meal, mean (median) | $0.038 ($0.031) | $0.008 ($0.008) |
| Cost per meal, lowest to highest | $0.021 to $0.071 | $0.004 to $0.010 |
| Model calls per meal, mean | 2.6 (3 of the 31 calls failed and cost nothing) | 3.5 (none failed) |
| Tokens per meal, mean | 5,508 in, 9,013 out | 9,339 in, 1,992 out |
| Time per meal, mean | 452 s (192 s per answered call on the free tier) | 7 s (2 s per call, not counting the 5 s gaps) |
With 3.8 Flash, extra calls drive the cost. The six meals with no rerun cost $0.021 to $0.036. The three whose kept recipe came from a rerun cost $0.041 to $0.071. The turkey and sweet potato meal cost $0.069: its first recipe reply broke the reply format and was asked for again. Per-meal detail: run 1 (c02, c03), run 2 (c01, c04, c05, c15), run 3 (c14), run 4 (c07, c10, c12) and run 5 (c09, c11). Flash-Lite costs about a fifth as much per meal although it makes more calls: its replies are short (1,992 output tokens per meal against 9,013), and 14 of its 15 meals needed a rerun. Per-meal detail: Flash-Lite run. The cost with Claude, the app's default model, has not been measured with a real API run.
Claude and Gemini on the golden set.
| Run | Model and route | Cravings | Checks passed | macros_vs_target |
|---|---|---|---|---|
| v3 | Claude, replies written by Claude Code subagents from the same prompts (not the API) | 15 | 165/165 | 15/15 |
| live-gemini | gemini-3.8-flash, live API calls | 12 of 15 | 130/132 | 10/12 |
| live-gemini-lite-2 | gemini-3.5-flash-lite, live API calls | 15 of 15 | 157/165 | 7/15 |
This is not a like-for-like comparison: the two runs reached the model by different routes, and Gemini covers 12 cravings. Gemini's two misses are both macros: the high-protein Bolognese at 691 kcal against a 600 kcal target, and the turkey and sweet potato meal at 40 g protein against a 45 g target. Both rerun calls failed (a 429 quota error, then a 503 high demand error), so no second recipe was written. The results file scores all 15 cravings and counts the 3 without a reply as failed (130/165).
Flash-Lite passes every format and food check but misses the macro targets on 8 of 15 meals. Its first recipe hit the targets in 2 of 15 meals, and its reruns often overshoot the other way: the chicken pasta went from 737 kcal to on target, then back to 654 kcal against a 500 kcal target. The scorer checks the last recipe. For that chicken pasta the app would show the second recipe, the one with the fewest problems, so by what the app shows Flash-Lite hits the macros in 8 of 15. Results file.
| Part | Source | License | Where |
|---|---|---|---|
| Code | This repo | AGPL-3.0 | LICENSE |
| Nutrition (first choice) | Ciqual 2025, ANSES | Licence Ouverte / Open Licence 2.0 (Etalab 2.0). Cite: Anses. 2025. Table de composition nutritionnelle des aliments Ciqual. https://doi.org/10.57745/RDMHWY | data/open/nutrition/ |
| Nutrition (where Ciqual has no good match) and loose produce weights | USDA FoodData Central | CC0 1.0 (public domain) | data/open/nutrition/, data/open/packs/ |
| Typical pack sizes | Open Food Facts, products sold in Spain (export of 2026-10-18) | ODbL 1.0, with its own LICENSE in the folder | data/open/packs/ |
| Estimated prices, Spain | MAPA, Panel de consumo alimentario en hogares, Aug 2025 to Jul 2026 | Reuse under Ley 37/2007 with attribution (not a named open licence) | data/open/prices/ |
The nutrition table has 138 foods (125 from Ciqual, 13 from USDA). Pack sizes cover 139 foods (102 from Open Food Facts, 20 from USDA portion weights, 17 set by hand with a reason in data/build/packs-overrides.json). Estimated prices exist for 76 of them, the ones with an exact or close match in the MAPA panel. Each of the 17 comunidades autónomas has its own price for 63 to 76 of those foods (only foods with data in every month the national price has); the rest use the national price. Each folder has a SOURCES.md with download dates, fields used and how the files were built.
BEDCA, the Spanish food composition database, is not used: its terms do not allow non-personal electronic use without written permission from AESAN.
Python 3.11 or newer and Node.js. From the repo root:
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt -r requirements-dev.txt
.venv/bin/python -m pytest -q
# engine on port 8100
.venv/bin/uvicorn api.index:app --host 127.0.0.1 --port 8100
curl http://127.0.0.1:8100/api/health
In a second terminal:
cd web
npm install
npm run dev # web app on http://127.0.0.1:3100, sends /api/evaluate to the engine on 8100
npm test # unit tests
npm run e2e # Playwright flow test; needs the engine and the dev server running, the model is mocked
One Vercel project with two services: the FastAPI engine and the Next.js web app, routed by vercel.json. Keep the Root Directory at the repo root. Details, sources and what is still untested are in docs/deploy.md.
api/index.py reads the request, computes the meal and returns it. The engine has no database, writes no files and makes no outside calls while it evaluates a meal. When the engine fails, it logs one line to stderr with an error id, the error type, code locations and the request's size and counts, never the request body, its values, headers or a key. Vercel, as the host, has its own request logs, which this code does not control.Python (standard library engine, FastAPI API, pytest), Next.js 16, React 19, Tailwind CSS 3, Playwright, Vercel Services.
Code: AGPL-3.0. Data files keep their own licenses and attribution, listed in Data and licenses.
Built by Marian Garabana.