An agentic RAG-powered dim sum waiter for Kinetic Canteen, Guelph, Ontario. Guests chat with the Dim Sum Enthusiast, an AI waiter that recommends dishes, manages a live cart, and wraps up orders with a local craft beer pairing.
- Conversational ordering - natural language chat to browse the menu, add/remove items, and manage the cart
- Agentic RAG - semantic menu search via Pinecone; conversation memory via FAISS
- Live cart - Supabase Realtime syncs cart state between the AI and the cart drawer instantly
- Order completion - structured order summary, Guelph brewery beer pairing, and automatic cart clear
- Session memory - conversation summarized every 3 turns to keep context concise
- Responsive UI - Next.js 14 App Router with Tailwind CSS, brand theme Guelph Gold & Steam
| Layer | Technology |
|---|---|
| Frontend | Next.js 14 (App Router), Tailwind CSS, Supabase JS |
| Backend | FastAPI, LangGraph, LangServe |
| LLM | OpenAI gpt-4o-mini + text-embedding-3-small |
| Vector DB | Pinecone (serverless, menu search) |
| Memory | FAISS (in-process, conversation summaries) |
| Database | Supabase (cart_items table + Realtime) |
AI Waiter/
|-- backend/
| |-- app/
| | |-- main.py # FastAPI app + LangServe mount
| | |-- config.py # Settings (pydantic-settings)
| | |-- graph/
| | | |-- state.py # AgentState TypedDict
| | | |-- nodes.py # agent, summarizer, signature_move nodes
| | | +-- workflow.py # StateGraph assembly + routing
| | |-- tools/
| | | |-- menu_search.py # Pinecone semantic search tool
| | | |-- memory_search.py # FAISS conversation memory tools
| | | +-- cart.py # Supabase cart tools (add/remove/get/clear)
| | |-- prompts/
| | | +-- persona.py # Dim Sum Enthusiast system prompt
| | +-- data/
| | +-- seed_pinecone.py # Seeds 52+ menu items into Pinecone
| |-- requirements.txt
| +-- .env.example
+-- frontend/
|-- src/
| |-- app/
| | |-- page.tsx # Redirects to /table/3
| | +-- table/[id]/page.tsx # Table page
| |-- components/
| | |-- ChatInterface.tsx # Main layout + order state
| | |-- CartDrawer.tsx # Slide-in cart panel
| | |-- MessageBubble.tsx # Chat message + menu item cards
| | |-- MenuItemCard.tsx # Add-to-cart card from AI response
| | |-- SuggestionChips.tsx # Quick-reply chips
| | |-- ChatInput.tsx # Message input
| | +-- TableHeader.tsx # Header with cart badge
| |-- hooks/
| | |-- useChat.ts # Chat state, streaming, suggestions
| | +-- useCart.ts # Cart state + Supabase Realtime
| +-- lib/
| |-- api.ts # Backend streaming API client
| |-- supabase.ts # Supabase client
| +-- types.ts # Shared TypeScript types
|-- .env.local.example
+-- package.json
START
-> agent_node (GPT-4o-mini + system prompt)
|-- tool_calls? -> tool_node -> agent_node (loop)
|-- order_complete? -> signature_move_node -> END
|-- every 3 turns? -> summarizer_node -> END
+-- otherwise -> END
Nodes:
- agent_node - main conversational agent with all tools bound; detects order-complete phrases
- tool_node - executes
search_menu,search_conversation_memory,add_to_cart,remove_from_cart,get_cart,clear_cart_tool - summarizer_node - condenses conversation every 3 turns; stores summary in FAISS and trims message history
- signature_move_node - fetches the real cart from Supabase, generates order confirmation + Guelph beer pairing, clears the cart
- Python 3.11+
- Node.js 18+
- OpenAI API key
- Pinecone account (serverless index named
dim-sum-menu, dimension 1536) - Supabase project
Run in the Supabase SQL editor:
create table cart_items (
id uuid primary key,
table_id text not null,
item_name text not null,
quantity integer not null default 1,
unit_price numeric(6,2) not null,
created_at timestamptz not null default now()
);
create index idx_cart_table on cart_items(table_id);Enable Realtime on cart_items in the Supabase dashboard under Database > Replication.
cd backend
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env
python -m app.data.seed_pinecone
uvicorn app.main:app --reload --port 8000backend/.env
OPENAI_API_KEY=sk-...
PINECONE_API_KEY=pcsk_...
PINECONE_INDEX=dim-sum-menu
SUPABASE_URL=https://<project>.supabase.co
SUPABASE_KEY=<anon or service role key>
cd frontend
npm install
cp .env.local.example .env.local
npm run devfrontend/.env.local
NEXT_PUBLIC_SUPABASE_URL=https://<project>.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=<anon key>
NEXT_PUBLIC_API_URL=http://localhost:8000
Open http://localhost:3000 — the app redirects to /table/3 by default.
| Method | Path | Description |
|---|---|---|
| POST | /chat/stream |
Stream the waiter agent response (SSE) |
| POST | /chat/invoke |
Invoke the waiter agent (blocking) |
| GET | /api/table/{id}/cart |
Get cart items for a table |
| DELETE | /api/table/{id}/cart/{item_id} |
Remove a cart item by ID |
| POST | /api/table/{id}/clear |
Clear cart and conversation memory |
| GET | /health |
Health check |
52+ items across 10 categories: Har Kau & Siu Mai, Bao & Buns, Rice & Noodles, Cheung Fun, Turnip Cake & Taro, Soup Dumplings, Spring Rolls & Crispy, Desserts, Beverages, and Seasonal Specials. Each item is embedded and stored in Pinecone for semantic search.
Guelph Gold & Steam
| Token | Value |
|---|---|
| Primary | #E83946 (red) |
| Secondary | #FF8800 (orange) |
| Tertiary | #FFD700 (gold) |
| Neutral | #121212 (near-black) |