pinch / README.md
Alptraum's picture
Update README.md
1c5a6fb verified
|
Raw
History Blame Contribute Delete
6.66 kB

A newer version of the Gradio SDK is available: 6.20.0

Upgrade
metadata
title: Pinch
emoji: 🀏
colorFrom: yellow
colorTo: green
sdk: gradio
sdk_version: 6.18.0
app_file: app.py
pinned: false
license: apache-2.0
tags:
  - build-small-hackathon
  - track:backyard
  - sponsor:openbmb
  - sponsor:modal
  - off-brand
  - best-agent
  - best-demo
  - tiny-titan

🀏 Pinch β€” photograph your ingredients, get a grounded plan

Build Small Hackathon 2026 · 🏑 Backyard AI track

Snap a photo of what's in your kitchen β€” Pinch works out what to cook, plans the seasoning grounded in real flavour science, and computes the amounts. A vision model reads the ingredients from your photo; an agent reasons over the Epicure flavour model (1,790 ingredients distilled from ~4M recipes) to decide what to add, what to substitute for what you lack, and in what order; and it runs Python in a sandbox for the quantitative side (servings, ratios, salt %, timing). Optionally, FLUX turns your ingredients photo into a picture of the finished dish.

Small models, each load-bearing, β‰ˆ24B total β€” under the 32B cap: MiniCPM-V (OpenBMB) sees the ingredients, Mellum 2 (12B, JetBrains) reasons about flavour, and FLUX.2 klein (4B) renders the dish.

Why this needs an agent

The hard parts aren't a lookup. Flavour β€” given the messy set of things in my kitchen and this dish, what's worth adding, and in what order? β€” is combinatorial and grounded in the Epicure pairing model, not the LLM's opinion. Arithmetic β€” scaling to servings, ratios, salt % β€” is something LLMs get wrong in their heads, so the agent offloads it to real code in a sandbox. The model reasons and sequences; the tools provide the facts.

πŸŽ₯ Demo video: https://www.youtube.com/watch?v=gpXQS35QWW0

πŸ“£ Social post: https://x.com/ssaacar/status/2066645089942708604

Architecture

  You: photo (or typed ingredients) + optional constraints
            β”‚  MiniCPM-V reads the photo β†’ ingredient list (you edit it)
            β–Ό   suggest_dish()  +  build_plan()
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  pairing_score  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚  JetBrains Mellum 2 (12B)  β”‚ ──────────────► β”‚  Epicure MCP (Kaikaku)     β”‚
   β”‚  strict-JSON planner loop  β”‚ ◄────────────── β”‚  pairing scores, neighbours β”‚
   β”‚                            β”‚   run_python    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚                            β”‚ ──────────────► β”‚  sandbox (kitchen math:     β”‚
   β”‚                            β”‚ ◄────────────── β”‚  amounts, ratios, timing)   β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   stdout        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                β”‚
                β–Ό  staged plan + amounts  ──►  (optional) FLUX.2 klein β†’ dish photo
  • Models: Mellum 2 reasons + writes the math code (served on Modal); MiniCPM-V reads the photo (OpenBMB's free hosted API); FLUX.2 klein renders the dish (HF Inference / fal-ai). All remote β€” the Space itself needs no GPU.
  • Flavour grounding: Epicure MCP β€” public, anonymous flavour server (find_pairings, pairing_score, neighbors, …) via a hand-rolled MCP client (epicure_client.py) with 404/429 retry + a disk cache. Each step's evidence is re-derived from a real pairing score, never the model's guess.
  • Sandbox: the quantitative math runs as real Python (sandbox.py), tailored to the dish type (a salad gets no simmer time; a dessert gets no savoury salt). SANDBOX_BACKEND=local|modal|mock.
  • Robustness: the model emits one JSON object per turn β€” an Epicure tool call, a run_python, or the finished plan (agent.py). If it doesn't converge, a grounded scripted planner (real Epicure scores + sandbox math, no LLM) takes over.
  • Honesty note: pairing scores are grounded facts; the substitution hint uses Epicure neighbors (co-occurrence, not a functional swap), so it's surfaced as "closest in flavour space," not "use X for the sourness of Y."

Run it

In the browser: add a photo (or type ingredients) β†’ Detect ingredients β†’ tidy the list to what you actually have β†’ Decide a dish & plan β†’ optionally ✨ See the dish.

Local dev:

pip install -r requirements.txt
cp .env.example .env     # fill in MODAL_REASON_URL, HF_TOKEN, etc.
python app.py
# fully offline (no models, scripted planner + sample detection):
MOCK_LLM=1 python app.py

Where the models run (inference backend)

Each model is configured independently via env vars (see .env.example).

Vision (MiniCPM-V) β€” VISION_BACKEND: has a free hosted API, so it runs real with no GPU.

VISION_BACKEND runs on cost
openbmb OpenBMB's free hosted API (api.modelbest.cn, OpenAI-compatible) free
zerogpu in-Space ZeroGPU free, quota
modal your Modal endpoint credits

Reasoning (Mellum 2) β€” INFERENCE_BACKEND: Mellum has no hosted API anywhere, so it runs on a GPU you control.

INFERENCE_BACKEND runs on cost
modal your Modal endpoint (no quota) credits
zerogpu in-Space ZeroGPU (40 min/day) free
mock (MOCK_LLM=1) scripted planner, no model free (dev)

Dish image β€” FLUX.2 klein: the "✨ See the dish" button renders the finished plate via HF Inference (provider="fal-ai"), billed to your account. Set HF_TOKEN; without it the button just shows a hint.

Deploy the Modal reasoning backend (one-time; pip install modal + modal token new):

modal deploy modal_app.py     # serves Mellum 2 on A100-40GB; weights cached in a Volume

It prints a URL. Set on the Space (Settings β†’ Variables & secrets):

INFERENCE_BACKEND=modal
MODAL_REASON_URL=<the printed url>
VISION_BACKEND=openbmb

min_containers=0 β†’ idle costs nothing; cold start ~30–60s (weights cached).