Spaces:
Running
A newer version of the Gradio SDK is available: 6.20.0
title: ShopStack
emoji: π
colorFrom: green
colorTo: blue
sdk: gradio
sdk_version: 6.17.3
app_file: app.py
pinned: false
tags:
- shopstack
- gradio
- inventory
- shopping
- offline-first
- household
ShopStack
Doc links: Several links in this README point to
Docs/paths that are intentionally local-only (seeDocs/README.md). They work in a local workspace but 404 from a clean clone. For canonical architecture, seeshopstack/module_registry.pyand the code undershopstack/. Git-tracked docs (MODEL_CATALOG.md, this README) are reachable from any clone.
Local-first, off-the-grid shopping intelligence platform. Know what you have, what to use soon, what to buy, what to skip, and where to buy from β without sending your data to the cloud.
ShopStack is a stack of shopping intelligence layers: home inventory (ShopStock), shopping lists and market baskets (ShopBasket), retailer price comparison (ShopCompare), scanning and import (ShopLens), price history and preferences (ShopMemory), and a reasoning agent (ShopAgent) that decides buy/skip/use-soon across all modules.
Philosophy
ShopStack runs entirely locally β SQLite database (WAL mode), mockable provider interfaces, and a Gradio workflow UI that works offline. The "Off the Grid" path means zero cloud dependencies for core functionality. The default mock providers let you build and test the full app without loading any ML models.
Total parameter limit: β€32 billion parameters across all loaded models.
Modules
| Module | Purpose |
|---|---|
| ShopStock | Inventory, pantry, fridge, expiry, low-stock, use-soon |
| ShopBasket | Shopping list, cart builder, market basket optimization |
| ShopCompare | Retailer price comparison (Swiggy, Blinkit, Zepto, ...) |
| ShopLens | Scanning: barcode, photo, receipt, barcode |
| ShopMemory | Price history, household preferences, field notes |
| ShopAgent | Reasoning: buy/skip/use-soon/compare decisions |
| Sources | Retailer datasets (Swiggy Instamart + future) |
See Docs/SHOPSTACK_PRODUCT_ARCHITECTURE.md for full details.
Gradio Workflows
ShopStack is organized around workflow experiences:
- Today β Decision-first dashboard: what to buy, skip, use soon, and compare
- Ask ShopStack β Natural language queries across all modules
- Shopping List β Create, classify (buy/skip/use-soon), and complete shopping plans
- Market Lens β Scan items via camera or voice, compare to inventory
- Add Purchase β Record what was bought (price, store, location)
- Find Item at Home β Search inventory by location and status
- Use Soon β Expiring and aging items flagged for attention
- Price Memory Check β Price history, trends, and best-store intelligence
- Traces β Workflow audit trail with redacted export
- Field Notes β Household notes and preferences
Quick Start
uv venv --python 3.13
uv pip install -e ".[dev]"
uv run python app.py
Open http://localhost:7860 in your browser.
Market Snapshot Import
ShopStack can ingest the real Swiggy Instamart fresh vegetables snapshot found in data/swiggy_fresh_vegetables_cards_6jun26.json (or the matching CSV) into the local price observation database.
uv run python scripts/import_swiggy_snapshot.py
Imported observations are tagged with source_event_id = swiggy_fresh_vegetables_20260606 so they can be filtered or audited later.
Tests
uv run pytest tests/ -v
uv run pytest benchmarks/ -v -m benchmark
Run uv run pytest tests/ --collect-only -q for the current test count.
Current Verified by Code Inspection
As of the current code inspection, the following metrics are verified:
- 26 Database Tables, 2 Views, 2 Triggers, 9 Indexes:
app_config,condition_events,correction_events,find_feedback,household_locations,household_members,household_objects,households,inventory_events,inventory_lots,market_record_components,market_records,market_snapshots,movement_events,negative_memory,object_notes,object_sightings,person_associations,preference_signals,price_observations,purchase_events,reconciliation_events,shopping_list_items,shopping_lists,stores,traces(Tables),price_history,agent_traces(Views). - 12 Tools: Including
semantic_find_item.
Note: For the canonical current-state metrics, run python3 scripts/repo_truth.py. The README is updated when new tables/tabs/tools are added; do not hand-maintain these numbers.
Engineering Mandate: Do not narrow scope to hackathon/MVP. ShopStack is designed as a long-term, bold, and comprehensive intelligence platform. Follow motto_v3.md principles exactly.
Project Structure
shopstack/
__init__.py
_version.py # v0.1.0
config.py # Settings (pydantic-settings, env prefix SHOPSTACK_)
model_registry.py # 16 candidate model entries (all β€32B total)
schemas/
models.py # All Pydantic domain models (14+ classes, 16 enums)
providers/
interfaces.py # 11 abstract provider ABCs
mock_providers.py # Full mock implementations for all 11 (Indian/Hinglish data)
registry.py # ProviderRegistry factory wired to Settings
persistence/
database.py # SQLite Database (WAL, 26 tables, 2 views, 2 triggers, 9 indexes, full CRUD)
services/ # Business logic services (decision engine, shopping, dashboard, preferences, freshness)
tools/
registry.py # ToolRegistry β 12 tools executing against Database
traces/
export.py # Trace creation, JSONL export, PII redaction
data_sources/ # Data source adapters for market snapshots and external feeds
ui/ # (reserved)
configs/ # (reserved)
app.py # Gradio Blocks UI entry point (workflow-first tabs, custom warm CSS)
tests/ # pytest test suite (run `pytest tests/ --collect-only -q` for current count)
benchmarks/ # pytest benchmark suite (9 latency markers)
Architecture
Gradio Blocks (app.py)
β ToolRegistry (12 tools, validates args, calls Database)
β Database (SQLite WAL, 26 tables, 2 views, 2 triggers, 9 indexes)
β ProviderRegistry (wired from Settings)
β MockProviders (default β 11 interfaces, all offline)
β Market services (market source registry load + snapshot status helpers in `shopstack.services.market_sources`)
β Settings (pydantic-settings, env-overridable)
β ModelRegistry (16 candidates, not loaded by default)
11 Provider Interfaces
| Interface | Mock Behavior |
|---|---|
STTProvider |
Returns predefined Hindi/Hinglish phrases |
TTSProvider |
Writes a note about what would be spoken |
VisionProvider |
Randomly samples from 26 common kitchen items |
ObjectDetectionProvider |
Returns plausible bounding boxes + confidences |
GroundingProvider |
Returns grounded item references |
SegmentationProvider |
Returns placeholder masks |
OCRProvider |
Returns mock extracted text |
PlannerProvider |
Returns structured multi-step plans |
ToolCallParserProvider |
Parses intent β tool call candidates |
EmbeddingsProvider |
Returns random 384-d vectors |
ImageEditProvider |
Returns a dummy edited image path |
12 Tools
| Tool | Purpose |
|---|---|
add_inventory_item |
Add a new item to household inventory |
update_inventory_item |
Update details of an existing inventory item |
consume_inventory_item |
Record consumption (partial or full) |
move_inventory_item |
Move an item to a different storage location |
find_item |
Search for an item across inventory and locations |
semantic_find_item |
Search for an item using exact, prefix, and semantic embedding search with match quality scores |
create_or_update_shopping_list |
Create/update the active shopping list |
compare_visible_item_to_inventory |
Compare detected item against current stock |
record_price_observation |
Record a price observation for an item |
get_use_soon_items |
Get items expiring or aging soon |
get_next_buy_suggestions |
Get suggestions for what to buy next |
export_anonymized_trace |
Export an anonymized agent trace |
10 Database Tables
inventory_lots, purchase_events, shopping_lists, shopping_list_items, household_locations, movement_events, price_observations, stores, traces, app_config
Compatibility aliases: price_history and agent_traces are exposed as read/delete-compatible views for older docs, tests, and scripts.
18 hierarchical household locations seeded on every init (safe via COUNT check): Home β Kitchen β Fridge β Fridge Door β ..., Pantry β Shelf β ..., etc.
Trace System
Every tool execution creates an agent trace stored in the database. Traces include perception snapshots, inventory context, decision rationale, proposed tool calls, and human confirmation status. On export, traces are redacted for PII:
- Phone numbers (10+ digits)
- Email addresses
- Aadhar numbers (12-digit pattern)
- PAN numbers (5 letters + 4 digits + 1 letter)
- Geo addresses (street patterns)
Explicitly not redacted: generic name fields, canonical item names, location names.
Screens
| Tab | Purpose |
|---|---|
| Plan Today's Shopping | Dashboard workflow β today view, use-soon signals, and shopping recommendations |
| Shopping List | View / create / manage the active shopping list |
| Market Lens: Should I Buy This? | Camera / voice input β detect β compare vs inventory |
| Add Purchase | Manual purchase recording form with store, price, item details |
| Find an Item at Home | Search + map lookup for likely storage location |
| Use Soon / Waste Saver | Expiring and aging items with priority list |
| Price Memory Check | Historical price observations per item |
| Find Item Location | Storage hierarchy and item count view |
| Model Stack | Active model stack + budget status and candidate catalog |
| Agent Trace | Agent session trace viewer with redaction preview |
| Field Notes | Agent reasoning and decision log |
Configuration
All settings are pydantic-settings with SHOPSTACK_ env prefix:
Operational resource guards are documented in Docs/RESOURCE_OPTIMIZATION_POLICY.md.
| Variable | Default | Description |
|---|---|---|
SHOPSTACK_DB_PATH |
data/shopstack.db |
SQLite database file path |
SHOPSTACK_APP_PORT |
7860 |
Gradio server port |
SHOPSTACK_OFF_THE_GRID |
true |
Use mock providers (no cloud) |
SHOPSTACK_LOCAL_AUTO_UNLOAD |
true |
Unload local model runtime after each local provider call |
SHOPSTACK_LOCAL_WHISPER_AUTO_UNLOAD |
true |
Unload local STT model after each transcription |
SHOPSTACK_TRACE_MAX_ROWS |
2000 |
Maximum number of trace rows to retain |
SHOPSTACK_TRACE_TTL_DAYS |
30 |
Delete traces older than this many days |
SHOPSTACK_STT_BACKEND |
mock |
STT provider selection |
SHOPSTACK_TTS_BACKEND |
mock |
TTS provider selection |
SHOPSTACK_VISION_BACKEND |
mock |
Vision provider selection |
SHOPSTACK_OBJECT_DETECTION_BACKEND |
mock |
Object detection provider |
... per-provider backends default to mock |
Model Catalog
See MODEL_CATALOG.md for the full living model catalog β including downloaded & tested models, parameter budget tracking, runtime backends (MLX, llama.cpp/GGUF, transformers), HF Pro and Modal Labs credit resources, and experiment logs.
The programmatic registry lives in shopstack/model_registry.py (16+ entries across STT, TTS, Vision, OCR, Embeddings, and Planner categories).
- Active / loaded models: actually selected at runtime.
- Candidate models: documented options available for future activation.
- Budget check: only active/loaded models are counted against the 32B cap (enforced by
validate_active_model_budget()).
Active design constraint: Total parameter count across all simultaneously active models must not exceed 32 billion. Mock mode shows an active-loaded stack of 0B.
Key Design Decisions
- Single shared schemas file β models are interconnected and share enums; a single file avoids circular imports.
- Provider ABCs named
*ProviderβSTTProvider, notSTT; mock classes namedMock*Provider. - PurchaseEvent enriched with per-item fields β
canonical_name,quantity,unit,total_pricelive on the event, not on a separate join table. - PriceObservation defaults β
observation_datedefaults todate.today(). - PII redaction is targeted β only phone, email, Aadhar, PAN, and address patterns are redacted. Generic
namekeys are preserved. - No auto-purchase or payment scraping β design-level constraint. ShopStack tells you what to buy, it doesn't buy for you.
Development
uv pip install -e ".[dev]"
uv run pytest tests/ -v
uv run pytest benchmarks/ -v -m benchmark
uv run python app.py
Deployment
ShopStack can run via Docker or on any of the supported platforms.
Docker (local)
docker compose up --build
# Open http://localhost:7860
Data persists in a Docker volume (shopstack_data).
Docker (standalone)
docker build -t shopstack .
docker run -p 7860:7860 -v shopstack_data:/app/data shopstack
Railway
- Push your repo to GitHub.
- Create a new project on Railway β Deploy from GitHub repo.
- Railway auto-detects
Dockerfileandrailway.json. - Add a Volume with mount path
/app/data(1 GB) for SQLite persistence. - (Optional) Set
SHOPSTACK_HF_API_KEYandSHOPSTACK_PLANNER_BACKEND=huggingfacefor cloud-backed planning.
Render
- Push your repo to GitHub.
- Create a new Web Service on Render β Deploy from Dockerfile.
- Select the Starter plan ($7/mo) β required for persistent disk.
- Add a Disk mount at
/app/datawith 1 GB. render.yamlis auto-detected if you connect via Blueprint.
Fly.io
# Install flyctl first: https://fly.io/docs/hands-on/install-flyctl/
flyctl launch --dockerfile ./Dockerfile
flyctl volumes create shopstack_data --region <your-region> --size 1
flyctl deploy
See fly.toml for configuration reference.
License
MIT