Your AI-Powered Recipe Assistant & Pantry Manager
A sophisticated multi-agent food concierge system that helps you discover delicious recipes based on what you already have in your pantry.
- Features
- Architecture
- Quick Start
- Setup Instructions
- Usage
- Deployment to Streamlit Cloud
- Project Structure
- Database Management
- Development
- Troubleshooting
- License
- Executive Chef (Orchestrator): Routes queries and coordinates agent collaboration
- Pantry Agent: Manages inventory with natural language commands via Model Context Protocol (MCP)
- Recipe Knowledge Agent: Performs hybrid search across recipe databases (Milvus/Qdrant)
- Sous Chef: Curates top-3 recommendations and adapts recipes to your pantry
- Hybrid Search: Combines semantic (vector) and keyword search for optimal results
- Pantry-Based Matching: Finds recipes that maximize use of your available ingredients
- Expiring Item Prioritization: Suggests recipes using ingredients that expire soon
- Smart Filtering: Respects dietary restrictions, allergies, and cuisine preferences
- Natural language inventory updates ("I have 2 chicken breasts and tomatoes")
- Automatic expiration tracking
- Quantity management with delta operations
- Persistent SQLite storage (
~/.leftovr/pantry.db)
- Beautiful Streamlit web interface
- Real-time chat-based interaction
- Visual recipe cards with metadata (prep time, servings, match percentage)
- Sidebar showing live pantry inventory and preferences
- Maintains conversation history
- Remembers user preferences across sessions
- Learns dietary restrictions and allergies
- Adapts recipes based on skill level
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Streamlit Frontend β
β (streamlit_app.py) β
βββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LangGraph Workflow Orchestrator β
β (main.py) β
β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β Executive β β Pantry β β Recipe β β
β β Chef βββΆβ Agent β β Knowledge β β
β β (Classifier) β β (MCP) β β Agent β β
β ββββββββββββββββ ββββββββ¬ββββββββ ββββββββ¬ββββββββ β
β β β β
β βΌ βΌ β
β ββββββββββββββββ ββββββββββββββββ β
β β SQLite β β Milvus/ β β
β β Pantry β β Qdrant β β
β β DB β β Vector DB β β
β ββββββββββββββββ ββββββββββββββββ β
β β
β ββββββββββββββββ β
β β Sous Chef β β
β β (Recommender)β β
β ββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
ββββββββββββ
β OpenAI β
β GPT-4o β
ββββββββββββ
| Agent | Role | Technologies |
|---|---|---|
| Executive Chef | Query classification, routing, general conversation | OpenAI GPT-4o |
| Pantry Agent | Inventory CRUD operations, expiration tracking | MCP Server, SQLite |
| Recipe Knowledge | Hybrid search, ingredient matching, recipe retrieval | Milvus/Zilliz, Qdrant, Sentence Transformers |
| Sous Chef | Recipe ranking, adaptation, customization | OpenAI GPT-4o |
Get Leftovr running locally in 5 minutes!
| Requirement | Where to Get | Required? |
|---|---|---|
| Python 3.8+ | python.org | β Required |
| OpenAI API Key | platform.openai.com | β Required |
| Zilliz Cloud Account | cloud.zilliz.com |
1. Clone the Repository
git clone https://github.com/your-username/leftovr-app.git
cd leftovr-app2. Create Virtual Environment
# Create virtual environment
python3 -m venv .venv
# Activate it
source .venv/bin/activate # macOS/Linux
# OR
.venv\Scripts\activate # Windows3. Install Dependencies
pip install -r requirements.txt4. Configure Environment Variables
# Copy example file
cp .env.example .env
# Edit .env with your favorite editor
nano .env
# OR
code .env # VS CodeAdd your credentials:
# Required
OPENAI_API_KEY=sk-proj-your-key-here
# Recommended (for recipe search)
ZILLIZ_CLUSTER_ENDPOINT=https://your-cluster.api.gcp-us-west1.zillizcloud.com
ZILLIZ_TOKEN=your-token-here5. Launch the App
streamlit run streamlit_app.pyThe app will open automatically at http://localhost:8501 π
For recipe search to work, you need to ingest the recipe database:
# Make sure environment variables are set
source .env # or set them in your terminal
# Ingest recipes to Zilliz Cloud (recommended)
python scripts/ingest_recipes_milvus.py \
--input assets/full_dataset.csv \
--outdir data \
--build-milvus
# This takes ~10-15 minutes for ~13,000 recipesAlternative: Skip this step and deploy to Streamlit Cloud instead (see Deployment)
Once running, try these commands:
π "Hi, what can you do?"
π¦ "I have chicken, tomatoes, and pasta"
π "Find me a recipe with chicken"
# Create virtual environment
python3 -m venv .venv
# Activate virtual environment
# On macOS/Linux:
source .venv/bin/activate
# On Windows:
.venv\Scripts\activatepip install -r requirements.txtCreate a .env file in the project root:
touch .envAdd the following variables:
# Required
OPENAI_API_KEY=your_openai_api_key_here
# Optional - For LangSmith tracing
LANGCHAIN_TRACING_V2=true
LANGCHAIN_API_KEY=your_langsmith_api_key
LANGCHAIN_PROJECT=leftovr-app
# Optional - For Milvus/Zilliz Cloud
ZILLIZ_CLUSTER_ENDPOINT=your_zilliz_endpoint
ZILLIZ_TOKEN=your_zilliz_token- Sign up at Zilliz Cloud
- Create a cluster
- Add credentials to
.env:ZILLIZ_CLUSTER_ENDPOINT=https://your-cluster.api.gcp-us-west1.zillizcloud.com ZILLIZ_TOKEN=your_token_here
Qdrant will be used automatically if Milvus is not configured. No additional setup needed.
# Ingest recipes into Milvus (preferred)
python scripts/ingest_recipes_milvus.py --input assets/full_dataset.csv --outdir data --build-milvus
# OR ingest into Qdrant (local)
python scripts/ingest_recipes_qdrant.py-
Tell Leftovr What You Have
"I have 2 chicken breasts, tomatoes, pasta, and garlic" -
Ask for Recipe Suggestions
"What can I make with these ingredients?" "I want something Italian and vegetarian" -
Get Top 3 Recommendations
- View recipe cards with prep time, servings, and match percentage
- See ingredient lists and direction previews
- Select a recipe (1, 2, or 3)
-
Receive Customized Recipe
- Adapted to your pantry
- Substitutions suggested for missing ingredients
- Formatted with step-by-step instructions
β
"Add 500g chicken breast, 3 tomatoes, and 1 onion"
β
"I ate 2 eggs"
β
"Remove the expired milk"
β
"Update garlic quantity to 5 cloves"
β
"Clear my entire pantry"
β
"Find recipes with chicken and tomatoes"
β
"I'm vegetarian and allergic to nuts"
β
"What can I cook in under 30 minutes?"
β
"Suggest Italian recipes for beginners"
β
"How do I dice an onion?"
β
"What's the difference between sautΓ©ing and frying?"
β
"Tell me about Mediterranean cuisine"
Deploy Leftovr to Streamlit Cloud for free with a cloud vector database!
Before deploying, you'll need:
- β GitHub Account - Fork/clone this repository
- β Streamlit Cloud Account - Sign up at share.streamlit.io
- β OpenAI API Key - Get from platform.openai.com
- β Zilliz Cloud Account (Recommended) - Sign up at cloud.zilliz.com
Zilliz Cloud provides managed Milvus for fast recipe search:
-
Create Account
- Go to cloud.zilliz.com
- Sign up (free tier available)
-
Create a Cluster
- Cluster Name: leftovr-recipes - Cloud Provider: AWS/GCP/Azure (any) - Region: Choose closest to your users - Cluster Type: Starter (free tier) or Standard -
Get Connection Details
- After cluster is created, click "Connect"
- Copy the Public Endpoint (looks like:
https://in03-xxx.api.gcp-us-west1.zillizcloud.com) - Copy the API Key/Token
-
Ingest Recipe Data
Run this locally before deploying:
# Set environment variables export ZILLIZ_CLUSTER_ENDPOINT="your_endpoint_here" export ZILLIZ_TOKEN="your_token_here" export OPENAI_API_KEY="your_openai_key" # Ingest recipes to Zilliz Cloud python scripts/ingest_recipes_milvus.py \ --input assets/full_dataset.csv \ --outdir data \ --build-milvus
This will:
- β Create embeddings for ~13,000 recipes
- β Upload to your Zilliz Cloud cluster
- β
Generate metadata files in
data/
-
Fork or Push to GitHub
# If not already on GitHub git init git add . git commit -m "Initial commit" git remote add origin https://github.com/your-username/leftovr-app.git git push -u origin main
-
Commit Required Files
Ensure these files are in your repo:
β streamlit_app.py β main.py β requirements.txt β agents/ β database/ β mcp/ β data/ingredient_index.json β data/recipe_metadata.jsonl -
Update requirements.txt
Make sure
requirements.txtincludes:streamlit>=1.28.0 openai>=1.0.0 langchain>=0.1.0 langgraph>=0.0.20 pymilvus>=2.3.0 qdrant-client>=1.7.0 sentence-transformers>=2.2.0 python-dotenv>=1.0.0 inflect>=7.0.0 pydantic>=2.0.0
-
Go to Streamlit Cloud
- Visit share.streamlit.io
- Sign in with GitHub
-
Create New App
- Click "New app"
- Select your repository:
your-username/leftovr-app - Branch:
main - Main file path:
streamlit_app.py - App URL (optional):
leftovror custom name
-
Configure Secrets
Click "Advanced settings" β "Secrets"
Add your secrets in TOML format:
# Secrets for Leftovr App # OpenAI API Key (REQUIRED) OPENAI_API_KEY = "sk-proj-xxxxxxxxxxxxxxxxxxxxx" # Zilliz Cloud Credentials (REQUIRED for recipe search) ZILLIZ_CLUSTER_ENDPOINT = "https://in03-xxx.api.gcp-us-west1.zillizcloud.com" ZILLIZ_TOKEN = "your_zilliz_token_here" # Optional: LangSmith for debugging LANGCHAIN_TRACING_V2 = "true" LANGCHAIN_API_KEY = "ls__xxxxxxxxxxxxxxxx" LANGCHAIN_PROJECT = "leftovr-production"
-
Deploy!
- Click "Deploy"
- Wait 2-3 minutes for initial build
- Your app will be live at
https://your-app-name.streamlit.appπ
Streamlit Cloud secrets are automatically available via st.secrets:
import streamlit as st
import os
# Access secrets (already implemented in streamlit_app.py)
os.environ["OPENAI_API_KEY"] = st.secrets.get("OPENAI_API_KEY", "")
os.environ["ZILLIZ_CLUSTER_ENDPOINT"] = st.secrets.get("ZILLIZ_CLUSTER_ENDPOINT", "")
os.environ["ZILLIZ_TOKEN"] = st.secrets.get("ZILLIZ_TOKEN", "")Once deployed, test these features:
-
β Pantry Management
"I have 2 chicken breasts, tomatoes, and pasta" -
β Recipe Search
"Find recipes with chicken" -
β View Inventory
"What's in my pantry?"
- Zilliz Cloud cluster created
- Recipe data ingested to Zilliz
- Repository pushed to GitHub
- Streamlit Cloud app created
- Secrets configured (OPENAI_API_KEY, ZILLIZ credentials)
- App deployed successfully
- Test all features
- Vector DB: Use Zilliz Cloud (managed Milvus) for best performance
- Caching: Streamlit automatically caches recipe searches
- Rate Limits: Be aware of OpenAI API rate limits
- Zilliz Cloud: Free tier available (1M vectors, 1 cluster)
- OpenAI: Pay-per-use (GPT-4o: ~$0.01-0.03 per conversation)
- Streamlit Cloud: Free tier includes unlimited public apps
- β Secrets stored securely in Streamlit Cloud
- β
Never commit
.envor API keys to GitHub - β Use environment-specific secrets for dev/prod
Enable LangSmith for production monitoring:
# In Streamlit secrets
LANGCHAIN_TRACING_V2 = "true"
LANGCHAIN_API_KEY = "your_langsmith_key"
LANGCHAIN_PROJECT = "leftovr-production"View traces, errors, and usage at smith.langchain.com
# Make changes locally
git add .
git commit -m "Update feature X"
git push origin main
# Streamlit Cloud automatically redeploys!Streamlit Cloud supports custom domains on paid plans:
- Go to app settings
- Click "Custom domain"
- Add your domain (e.g.,
leftovr.yourdomain.com) - Follow DNS configuration instructions
leftovr-app/
βββ agents/ # AI Agent implementations
β βββ executive_chef_agent.py # Query classification & routing
β βββ pantry_agent.py # Inventory management (MCP)
β βββ recipe_knowledge_agent.py # Hybrid search engine
β βββ sous_chef_agent.py # Recommendation & adaptation
β
βββ database/ # Data persistence layer
β βββ pantry_storage.py # SQLite operations
β
βββ mcp/ # Model Context Protocol
β βββ server.py # MCP server for pantry operations
β
βββ scripts/ # Utility scripts
β βββ ingest_recipes_milvus.py # Ingest recipes to Milvus
β βββ ingest_recipes_qdrant.py # Ingest recipes to Qdrant
β βββ evaluate_rag.py # Offline RAG evaluation & metrics
β βββ validate_pantry.py # Database validation
β βββ clear_pantry.py # Reset pantry database
β
βββ tests/ # Test suite
β βββ test_pantry_agent_comprehensive.py # Full pantry agent test suite (26 tests)
β βββ test_hybrid_search.py # Hybrid search tests
β
βββ data/ # Recipe metadata
β βββ ingredient_index.json # Ingredient mappings
β βββ recipe_metadata.jsonl # Recipe database
β
βββ assets/ # Raw datasets
β βββ full_dataset.csv # Recipe dataset
β
βββ qdrant_data/ # Qdrant vector storage
β
βββ main.py # LangGraph workflow orchestration
βββ streamlit_app.py # Streamlit web interface
βββ requirements.txt # Python dependencies
βββ .env # Environment variables (gitignored)
βββ .env.example # Environment template
βββ README.md # This file
The pantry inventory is stored in SQLite at ~/.leftovr/pantry.db.
python scripts/validate_pantry.pyOutput:
- Current inventory items
- Quantities and units
- Expiration dates
- Items expiring within 3 days
python scripts/clear_pantry.pysqlite3 ~/.leftovr/pantry.db
> SELECT * FROM pantry_items;
> .exit- Collection:
recipes - Embedding Model:
sentence-transformers/all-MiniLM-L6-v2 - Dimension: 384
- Collection:
recipes - Storage:
./qdrant_data/
We have a comprehensive test suite covering all features:
# Run comprehensive pantry agent tests (26 tests)
python tests/test_pantry_agent_comprehensive.py
# Expected output:
# Total Tests: 26
# β
Passed: 26
# β Failed: 0
# Success Rate: 100.0%
# π ALL TESTS PASSED! π
# Test hybrid search
python tests/test_hybrid_search.py
# Validate pantry database
python scripts/validate_pantry.pyThe comprehensive test suite covers:
- β Basic Operations (6 tests): Add, remove, update inventory
- β Natural Language (5 tests): Query interpretation
- β Edge Cases (5 tests): "as well", "too", "also", compound names
- β Food Validation (2 tests): Accept food, reject non-food items
- β Multi-Item Operations (2 tests): Batch operations
- β Clarification Flow (1 test): Multi-turn conversations
- β Expiring Items (1 test): Date-based filtering
- β Operations (4 tests): Consumption, deletion, viewing
Evaluate the quality of recipe search and retrieval using scripts/evaluate_rag.py:
# Run evaluation with default settings (20 samples, top-10 results)
python scripts/evaluate_rag.py
# Custom evaluation (50 samples, top-5 results)
python scripts/evaluate_rag.py --sample 50 --k 5
# Save results to custom output file
python scripts/evaluate_rag.py --output my_evaluation.jsonThe evaluation script uses graded relevance (0-2 scale) instead of binary matching:
- Grade 2 (Highly Relevant): Exact recipe match OR β₯80% ingredient overlap
- Grade 1 (Relevant): 50-80% ingredient overlap
- Grade 0 (Not Relevant): <50% ingredient overlap
User-Centric Metrics (Most Important):
- Success@K: Percentage of queries where user finds ANY usable recipe in top-K results
- β Excellent: β₯90%
- β Good: 70-89%
β οΈ Fair: 50-69%- β Poor: <50%
- Best Relevance MRR: Mean Reciprocal Rank of first highly relevant result
- Avg Best Rank: Average position of first grade-2 result
Quality Metrics:
- nDCG (graded): Normalized Discounted Cumulative Gain with 0-2 relevance scale
- Avg Relevance: Mean relevance grade across top-K results (scale: 0.0-2.0)
- Avg Ingredient Match: Percentage of query ingredients used by retrieved recipes
- Precision@K: Proportion of relevant results (grade β₯1) in top-K
Traditional Metrics (For Comparison):
- Exact Match MRR: Mean Reciprocal Rank of the exact original recipe
- Found in Top-K %: Percentage of queries where exact recipe appears in top-K
π EVALUATION SUMMARY (V3 - Advanced Metrics)
====================================================================
π Traditional Metrics (Exact Match Only):
Found exact recipe in top-10: 85.0%
MRR (exact): 0.456
Avg Rank (exact): 3.2
Median Rank (exact): 2
β¨ User-Centric Metrics (Graded Relevance):
Success@10: 95.0% β
β User finds ANY usable recipe in top-10
Best Relevance MRR: 0.712
Avg Best Rank: 1.8
β Position of first highly relevant result
π Result Quality:
nDCG (graded): 0.823
Avg Relevance: 1.45 / 2.0
Avg Ingredient Match: 68.5%
Precision@10 (relevant): 72.0%
π‘ Interpretation:
β
EXCELLENT: Users find usable recipes 95% of the time
Traditional RAG evaluation often measures exact match only (e.g., "did we retrieve the exact recipe?"), but for cooking:
- Multiple recipes can satisfy a query: If you have chicken and tomatoes, many different chicken-tomato recipes work
- Ingredient overlap matters more: A recipe using 8/10 of your ingredients is highly useful even if it's not the "original" recipe
- User success is what counts: Finding ANY good recipe is success, not just finding one specific recipe
The graded relevance approach better reflects real-world usage patterns.
For development and debugging, you can run the workflow in CLI mode:
python main.pyNote: This runs a hardcoded test conversation. Use the Streamlit interface for production.
# Install new package
pip install package-name
# Update requirements.txt
pip freeze > requirements.txtEnable LangSmith for workflow debugging:
LANGCHAIN_TRACING_V2=true
LANGCHAIN_API_KEY=your_langsmith_key
LANGCHAIN_PROJECT=leftovr-appView traces at smith.langchain.com
Cause: Vector database not set up or recipe data not ingested.
Solution:
python scripts/ingest_recipes_milvus.py --input assets/full_dataset.csv --outdir data --build-milvusCause: MCP server initialization failed.
Solution: Check that mcp/server.py exists and is valid. The app will continue without MCP but pantry operations may be limited.
Cause: Invalid or missing API key.
Solution:
- Verify
OPENAI_API_KEYin.env(local) or Streamlit secrets (cloud) - Check API key is valid at platform.openai.com
- Ensure you have credits/billing enabled
Cause: Using Qdrant (local) instead of Milvus (cloud).
Solution: Set up Zilliz Cloud for faster semantic search:
- Sign up at cloud.zilliz.com
- Add credentials to
.env(local) or Streamlit secrets (cloud) - Re-run ingestion script
Cause: Missing dependencies in requirements.txt
Solution:
- Check
requirements.txtincludes all packages - Push updated
requirements.txtto GitHub - Reboot app in Streamlit Cloud
Cause: Secrets not configured in Streamlit Cloud
Solution:
- Go to app settings β Secrets
- Add all required secrets in TOML format
- Reboot app
Cause: Heavy dependencies or large data files
Solution:
- Use
@st.cache_datafor expensive operations (already implemented) - Ensure recipe metadata files are committed to repo
- Consider upgrading to Streamlit Cloud paid tier for more resources
Cause: Multiple instances trying to access SQLite
Solution:
- Streamlit Cloud: Each user gets their own session (should work)
- Local: Close other running instances
- Check file permissions on
~/.leftovr/pantry.db
Cause: Network issues or wrong endpoint
Solution:
- Verify
ZILLIZ_CLUSTER_ENDPOINTis correct - Check cluster is running in Zilliz dashboard
- Verify token hasn't expired
- Try regenerating token in Zilliz dashboard
- LangGraph Documentation: langchain-ai.github.io/langgraph
- Streamlit Docs: docs.streamlit.io
- Milvus Documentation: milvus.io/docs
- Model Context Protocol: modelcontextprotocol.io
See LICENSE file for details.
- Recipe dataset from [source/attribution]
- Built with LangChain & LangGraph
- Powered by OpenAI GPT-4o
Made with β€οΈ and π½οΈ
Reduce food waste. Cook delicious meals. Enjoy your leftovers.