AI & Data5 November 20267 min read

From Conversation to Cart — Part 3 of 15

A recipe is not a basket

Recipes speak in cups and onions; catalogues speak in pack sizes and product codes. Part 3 of From Conversation to Cart shows why the two cannot be matched directly, and sets out the intermediate representation, unit roll-up and substitution rules that turn ingredient lines into a basket that makes sense.

#Agentic Retail#Data Governance#AI Engineering#Data Products#RAG
A shopper holding a phone in a grocery store at dusk, as a thread of light links highlighted produce on the shelves to a glowing basket on the counter.

A shopper plans three suppers for the week in the app: bobotie on Monday, chakalaka and pap on Wednesday, samp and beans on Friday. The plan is good. The basket contains three bags of onions, one for each recipe. It contains a 2 L bottle of milk for the single cup the bobotie needs, and a 2 kg bag of maize meal she already has in the cupboard. For the chakalaka it offers a jar of ready-made chakalaka, because the product title matched the recipe name better than any ingredient did.

Each line was a reasonable match on its own. The basket as a whole was wrong.

Ubuntu Grocer is a composite: a fictional South African grocery retailer whose scenario draws on lessons from real enterprise retail-agent delivery. Its people, systems and figures are illustrative and describe no single organisation. Part 2 traced the eleven stages from a request to a basket. This part opens up stages 3 and 4, where recipe lines become products, because that is where most bad baskets are made.

Three schemas that mean different things

A recipe line is written for a cook. "1 large onion, diced", "2 cups amasi or plain yoghurt", "a handful of morogo", "salt to taste". It mixes quantity, cooking unit, item, preparation and sometimes an alternative. The schema.org vocabulary, for example, allows recipeIngredient values to be free text, although structured values are also permitted.

A catalogue product is written for trade. It is a stock-keeping unit (SKU) with a fixed pack: a 1 kg bag of brown onions, a 2 L bottle of full-cream milk. Under the GS1 rules that govern product barcodes, a change to the declared net content printed on a pack requires a new Global Trade Item Number (GTIN), as GS1 member organisations' GTIN allocation guidance sets out. A 1 kg and a 2 kg bag of the same maize meal are different trade items.

An inventory record is written for operations: how many of a SKU are available at a store or fulfilment node for a slot, sometimes by weight rather than count.

"1 onion" has no product. A "1 kg bag" has no recipe. Something has to translate between them, and that something should be explicit.

An intermediate representation, hop by hop

Ubuntu Grocer never matches a recipe line straight to a product. Ruan Botha's AI engineering team and Sipho Nkosi's catalogue team agreed an intermediate representation: a small, stored record for each ingredient line that passes through five hops.

From recipe line to SKU, one hop at a timeSTAGEEXAMPLE: ONIONEXAMPLE: AMASIWHORecipe line as written1 large onion, diced2 cups amasi or yoghurtRecipeParsed lineqty 1 · size large · dicedqty 2 · cup · alternateModelCanonical ingredientonion (fresh, brown)amasi (fermented milk)MatcherBase-unit quantityabout 200 g, owned table500 ml (1 cup = 250 ml)CodeCandidate SKUs1 kg bag, 2 kg bagamasi 500 ml, amasi 2 LSearchChosen SKU and quantityroll up first, then 1 kgamasi 500 ml × 1CodeStore every hop with provenance, so a wrong line can be traced to its step
Ubuntu Grocer never matches a recipe line straight to a product. Each line passes through a parsed form, a canonical ingredient and a quantity in base units before any product is chosen, and each hop has a named owner: the model reads messy text, code does the arithmetic, and search proposes candidates from the catalogue. Storing every hop is what makes a wrong basket line debuggable.
  1. Parse the line. A model turns the free text into a structured line: quantity, unit, item, size, preparation, alternative and whether it is optional. This is genuine language work, including mixed-language lines such as "morogo, a bunch", and the model is good at it.
  2. Map to a canonical ingredient. The parsed item becomes a canonical ingredient from a list the catalogue team owns: "onion (fresh, brown)", "amasi (fermented milk)", "leafy greens: morogo". The matcher proposes the mapping; synonyms and local-language names live in the catalogue, not in a prompt. Part 5 covers why.
  3. Convert to base units. Code, not the model, converts the quantity into grams, millilitres or a count from an owned table: a cup is 250 ml, a large onion about 200 g, a medium one about 150 g (figures illustrative).
  4. Find candidate SKUs. Search returns products carrying that canonical ingredient, with pack sizes, attributes and prices.
  5. Choose SKU and quantity. Code picks the pack and count after the plan has been rolled up, and after hard constraints have filtered the candidates.

Two things make this worth the effort. A jar of ready-made chakalaka can no longer win on title similarity, because the matcher searches for "onion", "carrot" and "baked beans", not for the dish. And every hop is stored with its inputs, outputs and source, so when a shopper removes a line the team can see which hop went wrong: parse, mapping, conversion or pack choice. This is the same discipline as evaluating retrieval separately from the answer: score each hop on its own, or you will tune the wrong one.

Roll up before you match

The three bags of onions came from matching each recipe separately. The fix is to add up the whole plan first, by canonical ingredient in base units, and only then choose packs.

Roll up the plan before choosing packsTHREE SUPPERSROLL UPCHOOSE PACKSBOBOTIE, MONDAY2 onions1 tbsp curry powderCHAKALAKA AND PAP, WED1 onion500 g maize mealSAMP AND BEANS, FRIDAY1 onion500 g sampBY CANONICAL INGREDIENTOnion: 4 × 150 g = 600 gCurry powder: 15 mlMaize meal: 500 gSamp: 500 gOnions: 1 kg bag,400 g left overCurry powder: pantry,ask before addingMaize meal: pantry,ask, else 2 kg bagSamp: one 500 g bagcovers FridayWithout the roll-up, each recipe adds its own bag: three bags of onions
Three suppers in an illustrative weekly plan each ask for onions and other ingredients. Ubuntu Grocer converts every line to base units with an owned conversion table, adds them up by canonical ingredient, and only then chooses pack sizes. Pantry staples become a question for the shopper rather than an automatic purchase.

In the worked example, four onions across three recipes become 600 g: one 1 kg bag, not three. Pack choice then follows a stated policy: the smallest set of packs that covers the need, unless a larger pack costs less per kilogram and the leftover keeps. Onions keep. Coriander bought on Monday for Friday does not, so perishables are checked against the plan's dates.

The conversion tables matter as much as the catalogue and need an owner: a cup of maize meal and a cup of milk weigh different amounts. Sipho's team owns the table, versions it and reviews the entries behind the most-edited basket lines first. It is the grocery equivalent of the argument in the semantic layer is your hallucination control: a definition the agent can read beats a guess the agent makes.

Pantry, fresh and the question worth asking

Rice, maize meal, oil, salt and spices are pantry staples, and a basket that buys them every week loses trust quickly. Milk is not: it is fresh, so the plan buys the smallest pack that covers the cup, 1 L rather than 2 L, and checks its date against Monday.

When a rolled-up plan needs a staple, the review screen shows a single checklist ("Do you already have: maize meal, oil, curry powder?") with each item pre-ticked from what the shopper has told the assistant before, so one tap removes it. It is part of the screen, not another chat turn, which matters on a small data bundle. The answers update her pantry record. Part 4 treats each pantry answer as a claim about a cupboard: the assistant leaves the item out and says so, rather than assuming.

Substitution has semantics

"Substitute" hides three different decisions, and treating them as one is how a basket quietly changes the meal.

  • Same ingredient, different product. A 1 kg bag instead of two 500 g bags, or another brand of the same canned beans. Low risk: re-run quantity and price, and show the change.
  • Different ingredient, same role. Plain yoghurt for amasi, spinach for morogo, flat-leaf parsley for coriander. This changes the dish, so it needs the shopper's consent, and the model is useful here for proposing candidates that play the same role in the recipe.
  • Never substitute. A brand the shopper has pinned, or a line where no candidate passes the hard constraints (a declared allergy, a halaal or kosher requirement). Show a gap instead.

Every substitute goes back through the hard constraints: the allergen check runs on the product that will be delivered, not the one first chosen. In our reviews of retail-agent programmes, this is one of the checks most often missing.

Where the model belongs

The model reads messy language, proposes canonical mappings and suggests same-role substitutes. Code converts units, rolls up the plan, rounds to packs and enforces constraints. The catalogue team owns the canonical list, synonyms and conversion tables.

The trade-off is maintenance: these tables are never finished. Ubuntu Grocer started with the few hundred ingredients behind most lines in its recipe library, and sends anything the matcher cannot map confidently to a review queue rather than guessing. Each cleared entry improves future baskets.

Run again, the three suppers produced one bag of onions, carrots and baked beans instead of a ready-made jar, and a checklist that let the shopper untick maize meal and curry powder. The basket was smaller, cheaper and right.

Questions to take into your architecture review

  1. Do you match recipe lines straight to products, or through a stored intermediate representation?
  2. Who owns the canonical ingredient list, its synonyms and its local-language names?
  3. Where do unit conversions happen, who owns the table, and is it versioned?
  4. Are ingredients rolled up across the whole plan before packs are chosen?
  5. What is your pack-choice policy, and does it consider perishability against the plan's dates?
  6. How are pantry staples handled: guessed, always bought or confirmed by the shopper?
  7. Do you distinguish same-product, same-role and never-substitute cases, and does every substitute re-run the allergen and dietary checks?

Key points

  • Recipes, catalogues and inventory use different schemas and units. "1 onion" has no product; a "1 kg bag" has no recipe.
  • Translate through an explicit, stored intermediate representation: parsed line, canonical ingredient, base units, candidate SKUs, chosen SKU and quantity.
  • Roll up the whole plan by canonical ingredient before choosing packs, then apply a stated pack and perishability policy.
  • Substitution is three decisions, not one, and every substitute re-runs the hard constraints.
  • The model reads language; code does arithmetic; the catalogue team owns the tables.

CloudNala's point of view

The temptation is to let a capable model go straight from recipe to basket, because in a demonstration it looks almost right. Almost right is the problem: three bags of onions is not a failure anyone catches in testing, but shoppers notice it every week. The intermediate representation is unglamorous, and it makes the basket debuggable and measurable. We would build it before tuning a single prompt.

Next: Part 4, Personalisation is a constraint system. All parts are on the series page.

How CloudNala can help

CloudNala helps retail teams design the recipe-to-basket layer: the intermediate representation, canonical ingredients and their owners, conversion tables, pack policies and substitution rules. We use shopper edits as evidence of where your matcher fails today, and set out the data work that fixes it.


Work with CloudNala

CloudNala helps organisations move from technology ambition to practical execution across cloud, AI, data, platform engineering and digital services.

Whether you are exploring AI, modernising your cloud environment, building a public-sector digital service, or turning an idea into a working MVP, we can help you shape the roadmap and deliver the next step.

Book an Agentic Retail Review or write to us at consult@cloudnala.co.za