## Inspiration

I cook most days, and every app I tried treated the kitchen as a database: a list to fill, a counter to hit. I wanted something closer to a kitchen with people in it. A cook who has taste. Someone who runs the list and knows my supermarket. Someone who remembers that I cannot eat gluten without being told twice. Apple Intelligence made that possible on the phone itself, and Private Cloud Compute made it possible for the jobs the phone cannot carry, with the same privacy. The question I wanted to answer with Raviolo is whether a cast of small, well-defined assistants running on Apple's models can be good enough to trust every day, and how to know.

## What it does

Raviolo is a kitchen companion for cooking, shopping and eating well, with five assistants, each with one job and a character of its own.

- **Misto Manzo**, the cook, writes recipes from what is in the fridge or for a dish by name, refines them, declines the ideas that would spoil a dish, and helps while the pan is on.
- **Spinacio** runs the shopping list. Items land in the right section of the person's own supermarket, in the order they walk it; duplicates merge, quantities add up, every merge can be undone.
- **Olio** reads the plate for protein, fiber and good fats and suggests the one addition that would balance it. Never calories, never a lecture.
- **Ricotta** keeps the notebook: allergies, intolerances and dislikes, said once and respected in every recipe and every plate from then on.
- **Amaretto** answers facts and techniques, and steps in by himself when a question is his.

Recipes can be saved from any link, scaled, and sent to the list. What gets ticked off the list becomes the pantry, and the cook sees it. The app shows which model answered under every reply, and when no model can answer it says why and where to fix it.

## How we built it

The core is Kotlin Multiplatform (recipes, list, pantry, notebook, the chat router, SQLDelight storage) with a SwiftUI app on top. The subscription runs on RevenueCat.

The models are reached through **VoltaSDK**, an open-source Swift package I wrote for this: it resolves which model answers each call (on-device Foundation Models, Private Cloud Compute, or a cloud key), falls back at runtime when one is unavailable or out of quota, discloses privacy crossings, and keeps every call self-contained so the app owns the conversation.

The part I am most attached to is the evaluation layer. Every assistant behaviour is a task: the app's instructions verbatim, the JSON shape it expects, real inputs in each language, and pass rules. The tasks run on Apple's Evaluations framework through the SDK, against each tier, and the results form a capability map, 171 measured rows over 81 tasks at submission. That map ships inside the app and gates the chain per task: a model that measured below the floor for a job is skipped for that job, so a recipe for a named dish goes to Private Cloud Compute first (10/10 against 6/10 on-device) while a shopping remark stays on the phone (23/23).

The chat has no intent classifier. A fixed list of rules reads each message, the first match wins, and the model only writes the reply in the shape the rule chose. The one classifier I tried read 0 of 4 bare food names right.

## Challenges we ran into

The first day gave 0/20 on the meal record. The on-device model copied the enum specification literally into its values (`"present|light|missing"` returned as the value). Constraining output to a schema took validity from 0% to 100% in one step, and that became a feature of the SDK.

Prompts on a small model behave unlike prompts on a large one, and each lesson cost a run. Naming a thing primes it: a banned-words sentence produced the banned words, and "do not mention Ricotta" produced "Ricotta, you're making me flustered". An example sentence in the instructions came back verbatim whatever the meal. Two rules pulling against each other ("gluten means no pasta" and "gluten-free pasta is welcome") scored 0/8 on-device in three phrasings while PCC held the exception, so the notebook calls route to PCC and the recipe carries a deterministic rule. A persona simile became speech: described as talking "the way a friend at the gym talks about a good set", the cook put sears and lifts in every reply. Descriptions are for the model; the character never says what they are like.

Private Cloud Compute has a daily quota that dies mid-run after a few hundred calls. Three measurement passes were lost to it before every merge checked availability first.

## Accomplishments that we're proud of

A cast that reads as characters without ever describing itself. A capability map that decides routing with numbers instead of guesses. A shopping list whose design was chosen by four datasets before any code existed: sectioning works on both tiers, reading a store from a description is PCC-only, and merging splits by shape (one pair on-device, the whole list on PCC). A failure message that names its cause and links to the switch that fixes it. And an SDK that other developers can use for the same discipline.

## What we learned

Quality on these models is measured, never asserted; the beliefs I started with were wrong in both directions (on-device keeps a list across turns fine once output is structured, and it cannot hold an exception against a rule at all). Rules first, model second, and every wrong reading should cost a tap rather than a wrong list. A dataset written before the feature decides the feature.

## What's next for Raviolo

The real-iPhone row of the map (every on-device number so far is the Mac's model standing in). Recipe extraction measured on seventy-six real pages from twenty sites in five languages, which is in progress. Cloud tiers and a model judge once keys are in place. More languages for the assistants, and a sixth character or two once the kitchen asks for them.

Built With

  • appleintelligence
  • kmp
  • swift
  • swiftui
Share this project:

Updates

Submission history