Four local models and a human approval at every step, on one 8 GB GPU.
My MSc dissertation. A five-stage agentic workflow turns a hospitality client's intake form into a consultant-grade menu brief. Each stage reads only what the approved stage before it hands over. Open-weight models draft, another model family reviews, code checks what they miss, and a consultant approves each step.
Private industry code; a demonstration is available on request.
- Sector
- Hospitality
- Method
- Agentic AI and local LLMs
- When
- Jul – Sep 2026
- Context
- MSc dissertation with a UK hospitality consultancy (paper mark 85)
- Role
- Solo: requirements, workflow, evaluation, deployment and handover
Key figures
- 4 open-weight models on one 8 GB GPU
- 16.7 min for all five stages of an 8-dish brief on that GPU
- 1,500+ automated tests at handover
How a brief is made, stage by stage
- A model runs here
- Deterministic code
- An outside source
- A stored artefact
- A boundary the design refuses
-
Five stages, a person at every gate
A consultant fills in the client's intake form. Five stages then draft the brief, and each starts only when the stage before it is approved. A stage reads only what the approved stage before it hands over, and editing an earlier stage marks every later one stale. Four model roles load one at a time within the GPU's 8,188 MiB: Qwen3.6 35B-A3B drafts Stages 1, 2, 3 and 5, gemma-4-E4B composes the dishes, and Gemma 26B and gpt-oss-20b review work they did not write.
Open full size: Five stages, a person at every gate -
Market research from free public sources
Stage 2 starts from one point: the postcode, with a town search as the fallback. Map queries collect hospitality venues within 1.5 km, widened to 4 km when fewer than 30 are named, and demand generators within 800 m, alongside census, deprivation, hygiene-rating, company and food sources. Every response is cached with its URL, status and time, and one dead source never stops the bundle.
Open full size: Market research from free public sources -
Reading a rival's menu, cheapest method first
A cross-encoder chooses ten nearby venues to profile, and each menu is read by the cheapest method that works: structured data, page text, menu pages, the PDF text layer, and a vision model only when a PDF is an image. On real menu PDFs, 83% had a usable text layer, so the vision model is the exception. Each rival yields a median price, the samples it rests on, up to twelve dishes and its own description.
Open full size: Reading a rival's menu, cheapest method first -
An evidence graph where every link has a source
Venues from the map and the hygiene register are matched into one list and fused with cuisines, dishes and the location into a NetworkX graph. Every edge records its source and a confidence. A safe renderer turns raw totals into bounded phrases before any model reads them. Two projections leave the graph: the Stage 2 one never contains a dish name, and the Stage 4 one is stored but never given to the dish composer.
Open full size: An evidence graph where every link has a source -
One reranker, four rankings
A BGE cross-encoder, loaded once, ranks which ten competitors to profile, the Stage 4 dish pool, the description kept for each rival and every dish's brand fit. A cheaper embedding prefilter was tested and declined: its recall at 20 was 0.644 against 0.333 by chance, too weak to discard candidates, so the bounded pools are scored in full.
Open full size: One reranker, four rankings -
A strategy that can only cite what was found
Facts are grouped into seven fixed facets and the model writes one summary per facet. Its output schema accepts only that facet's fact identifiers, so an invented citation cannot decode, and a verifier drops any uncited sentence. The strategy is written in three ordered passes, then read by two models that did not write it: Gemma 26B as a defect gate and gpt-oss-20b as advice. This proves a citation belongs to the evidence, not that the evidence is true.
Open full size: A strategy that can only cite what was found -
Stage 3 turns the brief into numbers a check can prove
Stage 3 reads the approved brief and strategy, never the must-have lists. A model proposes the sections, counts, protein mix and price mix, and a classifier sorts the must-have dishes. Nine deterministic repairs then pin the client's counts, reserve dietary slots and derive the daypart matrix. The demo client's request for one vegan main becomes the typed cell "vegan": 1, which Stage 4 has to account for.
Open full size: Stage 3 turns the brief into numbers a check can prove -
Stage 4 drafts dishes as a set, then checks them
The binding rules are rebuilt for every section: exclusions, sourcing commitments, dietary provisions and the must-haves, which are placed first. gemma-4-E4B drafts each section as a set, so it sees the neighbouring dishes, then labels each dish's protein, price tier and fit. Code rejects placeholders, duplicates and conflicts, and asks the model again only for the missing cell, within fixed budgets. The same model drafts and labels, so an independent read comes later.
Open full size: Stage 4 drafts dishes as a set, then checks them -
Selection is a search, and a shortfall comes with a proof
No model picks the final menu. A search over up to 120,000 combinations per section chooses it under declared priorities: must-haves and exact counts never relax, and softer preferences give way in a fixed order. When a section cannot be filled, a maximum-flow certificate names the protein and price classes the dish pool cannot serve together. The shortfall is printed in the client's document, never silently cured.
Open full size: Selection is a search, and a shortfall comes with a proof -
Every check runs again after the menu settles
Enrichment, rewrites, deduplication and reconciliation change the menu after selection, so every audit runs again on the final text. Dietary claims are amended, weakened or withdrawn, for example vegan to vegetarian, rather than left wrong. Allergen claims are removed and left to supplier data and the operator's sign-off. gpt-oss-20b then reads the whole menu as advice only, and a person approves the stage.
Open full size: Every check runs again after the menu settles -
Review findings ordered by consequence
The first review screen had 43 points that could raise a finding, shown in 13 different ways across four panels, all weighted the same. On one menu, 11 of 17 flags were price-tier arithmetic and none named the defect that decided its grade. Findings are now ordered by the consequence of not responding, after the medical-device alarm standard IEC 60601-1-8, so the serious one comes first.
Open full size: Review findings ordered by consequence -
Six kinds of guardrail, none of which compares
Every guarantee in the route is one of six kinds: approval and staleness gates, grammar-locked output schemas, selectors with declared relaxation, repairs with fixed budgets, audits recomputed after rewriting, and disclosures printed in the document. None compares the output with a right answer, because there is none. Each proves a property of the state it can read, never of the world.
Open full size: Six kinds of guardrail, none of which compares -
One laptop, behind an outbound tunnel
The pilot ran on one Windows laptop with an 8 GB GPU. The consultant signed in through a Cloudflare tunnel that dials out, so no router port was opened. FastAPI serves the five approval gates and keeps every generated, edited and approved version, and the model loader keeps one model in memory at a time.
Open full size: One laptop, behind an outbound tunnel -
What the consultant receives
The finished project page for the demo client. The brief downloads as a Word document with tracked changes on, so the consultant's edits stay visible. It states what it leaves out: allergen data, prices, and menu copy that stays indicative until checked against the recipe. Points the client never answered are printed as questions, and tensions such as a gross-profit target outside the usual band are raised, not decided.
Open full size: What the consultant receives
Numbers on this page come from the MSc dissertation (2026) and the system's own run records. The code and the client material are private; the screens show a fictional demo client.
How it was evaluated
-
A harness that never runs in production
A menu brief has no answer key, so the evaluation compares runs instead. The offline harness clones frozen, approved upstream state so that only the part under test changes, records the model and decoder settings, reruns the same scorers and keeps every document and verdict. Each instrument is labelled by how far it can be trusted: the dietary-claim check reached 91% precision and about 92% estimated recall on 80 hand-labelled dishes, and the whole-menu judge is advisory only.
Open full size: A harness that never runs in production -
Fifteen configurations screened on the 8 GB GPU
Speed came first, as a feasibility screen: the predicted decode speed of every configuration that fitted within 8,188 MiB, from 1.6 to 108.5 tokens per second. The darker bar is the model deployed at Stage 4. Speed only decided which models could be tried; whole documents decided which one was good enough.
-
The fastest model was not the best one
On one full route, Qwen3.6 35B took 37 minutes and its brief graded C; gemma-4-E4B took 22 and Qwen3-4B 16, and both graded D. Then the upstream stages were frozen and only Stage 4 was swapped, for six clients: gemma-4-E4B graded B, C, C, C, D and D, and Qwen3-4B graded D all six times while running faster. gemma-4-E4B was deployed: it beat Qwen3-4B in the paired runs at about half the 35B's Stage 4 time.
-
Where 551 candidate dishes went
In one larger profile, the Stage 4 loop drafted 551 candidates to deliver 74 dishes, and 64% of model time went to checks and repairs rather than writing. Most candidates were removed by deterministic checks, not by a model: 320 failed the distinctness fence and 35 the name check, while the model judge rejected 21. The recorded source does not attribute 101 to a single gate, and the chart says so rather than guessing.
-
The shortfall the labels missed
Every structural check first trusted the dietary label the model wrote beside each dish. A hand recount of the dishes' components found up to 47 dishes short of the plan, up to 37 more than the labels reported, in all five composition architectures. A resolver on the settled menu cut the worst case from 46 to 26. That is safe degradation, not proof of dietary compliance, so allergen indication was taken out of the generated brief.
-
Four results, each with what it rests on
Narrowing what the model must cite beat giving it more to read: a wider projection cut the citations in the delivered strategy from three to one, while identifier-locked synthesis raised them to seven. Over 25 identical upstream states, neither composition architecture won outright. Every planned section count was delivered in 24 of 24 documents. And whole documents, not speed, chose the Stage 4 model.
Open full size: Four results, each with what it rests on
A to D grades are provisional predictions by a model from another family, read against a written rubric, not consultant grades. Most comparisons are single draws: they show mechanisms, not average effects.
The question
A hospitality consultancy turns each client’s intake form into a menu development brief. Can open-weight models on one consumer GPU draft that brief, with a consultant approving every step and nothing the client relies on left unchecked? This was my MSc dissertation, built with a UK consultancy; its code and the client material stay private.
Built from the consultancy’s own brief
The requirements came from the consultancy’s developer brief and its archive of example files. No example input came with its finished output, and a menu has no single right answer, so there was nothing to score against. The design answers a narrower question: which properties of the brief can be guaranteed, and at which stage. An approval records the hashes of everything upstream, so an earlier edit marks every later stage stale instead of silently keeping work that no longer matches.
Deployed and handed over
It ran as a private pilot behind an authenticated tunnel, on four open-weight models sharing one 8 GB GPU, and was handed over with over 1,500 automated tests and an operating manual. A practising consultant approved four of the five stages without edits and judged the output usable with minor edits.
Limits
- The code and the client’s material are private: this page describes the work, and a demonstration is available on request.
- The verdict comes from one practising consultant on a pilot, not from a measured effect across many clients.
- The A to D grades used to compare runs are a model’s provisional predictions against a written rubric, not consultant grades.
- No stage can guarantee that a source is true, that a dish meets a dietary claim, or that the menu will be profitable. Those stay with the consultant.