--- title: BreadBuddy emoji: ๐Ÿž colorFrom: yellow colorTo: gray sdk: gradio sdk_version: 6.18.0 python_version: '3.11' app_file: app.py pinned: false tags: - track:backyard - sponsor:openbmb - sponsor:modal - achievement:offbrand - achievement:llama - achievement:fieldnotes --- # BreadBuddy ๐Ÿž AI-powered bread baking assistant โ€” diagnose what went wrong, get fixes, and learn to bake better. Built over 10 days for the Hugging Face ร— Gradio Build Small Hackathon. All models โ‰ค 32B, self-hosted, no proprietary APIs. ## Features | Feature | Description | Model Pipeline | |------|------|------| | ๐Ÿž Photo + Text Diagnosis | Upload a bread photo with description โ†’ structured 3-part diagnosis (causes / fixes / recipes) | MiniCPM-V 4.6 โ†’ Gemma-4-12B | | ๐Ÿ’ฌ Follow-up Chat | Drill deeper on diagnosis results โ€” multi-turn conversation with context memory | Gemma-4-12B | | ๐ŸŒ™ Dark Mode | Full dark bakery theme with custom CSS/JS | Gradio 5.50.0 | All responses streamed in real-time via SSE (Server-Sent Events). Reasoning content visible in a collapsible panel. ## Architecture ``` User (Photo + Text) โ”‚ โ–ผ โ”Œโ”€ Gradio Frontend (deploy/app.py) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Single-tab clinic UI ยท Dark bakery theme ยท Custom CSS/JS โ”‚ โ”‚ Streams SSE: reasoning_content + content dual channels โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ POST /v1/chat/completions (OpenAI-compatible) โ–ผ โ”Œโ”€ Modal Gateway (CPU, gateway.py) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Unified routing: has_image? โ†’ call_vision() : call_agent() โ”‚ โ”‚ ReAct loop (OpenAI function calling) ยท SSE streaming โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ has_image? no image โ”‚ โ”‚ โ–ผ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ MiniCPM-V 4.6 โ”‚ โ”‚ โ”‚ Modal L4 GPU โ”‚ โ”‚ โ”‚ Vision analysis โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ vision context โ”‚ โ–ผ โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Gemma 4 12B (GGUF Q4_K_M) ยท llama.cpp ยท Modal A10G โ”‚ โ”‚ 8K context ยท 8 concurrent slots ยท OpenAI-compatible API ยท -n 4096 โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` ## Key Engineering Decisions - **Unified Gateway Pattern** โ€” single endpoint, stateless routing. Gateway on CPU (<2s cold start), models on GPU (independent scaling). Eliminates cross-service contract drift. - **ReAct Agent (Gateway-embedded)** โ€” OpenAI function calling directly in gateway, no LangGraph dependency. Reduced 3 fragile cross-service contracts to 1. - **llama.cpp with `-n 4096`** โ€” discovered and fixed a server-side 1000-token hard limit that silently truncated output. Root cause debugging took 3 repair cycles across server/client/parser layers. - **content + reasoning merge rendering** โ€” tolerant of non-deterministic LLM output. Reasoning often contains complete diagnosis even when content is truncated. - **Custom Gradio UI** โ€” deep CSS/JS override beyond default theme. Dark mode with localStorage persistence. ## By the Numbers | | | |------|------| | **Development** | 10 days (June 5โ€“15, 2026) | | **Code** | ~2,000 lines Python (deploy + modal) | | **Tests** | 54 tests (41 unit + 13 E2E with Playwright) | | **Commits** | 40+ | | **Deployments** | 15+ modal deploy | | **Design docs** | 25+ (architecture decisions, retrospectives, checklists) | | **Architecture decisions** | 6 (2 revised from scratch) | BreadBuddy screenshot ## Challenges Solved The most interesting bug: **E2E tests passed locally but the recipe section never rendered in production.** After 3 repair cycles across 4 agents, the root cause was traced to **llama.cpp's default `-n 1000` token limit** โ€” Gemma-4's reasoning consumed ~70% of the budget, starving the visible content. The fix chain: `/no_think` hack โ†’ server-side `-n 4096` โ†’ content+reasoning merge rendering. Full retrospective: [technical-retrospective.md](https://github.com/iweb3insight/ceo-worktree/blob/master/1-Run/instructions/2026-06-15-BreadBuddy-%E9%A1%B9%E7%9B%AE%E5%A4%8D%E7%9B%98.md) **Gateway code rot** โ€” three independently-deployed services (Gateway / MiniCPM / Gemma) drifted apart: mismatched routes, wrong response keys, dead code path. Fixed by reducing interface contracts from 3 to 1. ## Methodology This project was built with two AI-assisted development frameworks: - **Harness** (AGENTS.md + TDD + Skills + Memory) โ€” project constitution, red-green-refactor, mandatory verification before success claims. AGENTS.md as a living document, 50+ cross-session memory entries. - **Architecture Loop** (Judge/Builder separation) โ€” frozen acceptance gates before implementation, "nobody grades their own work," mandatory builder disagreements. Evaluated and documented applicability boundaries (best for incremental changes, not greenfield prototypes). Key lesson: **Verify the premise before building.** 30 minutes of Gemma function-calling compatibility tests saved 2 days of potential rework. ## Tech Stack | Layer | Technology | |----|------| | Frontend | Gradio 5.50.0, custom CSS/JS, dark mode | | Text Model | Gemma 4 12B (GGUF Q4_K_M) via llama.cpp b9518 | | Vision Model | MiniCPM-V 4.6 via Transformers | | Gateway | FastAPI + Python 3.11, CPU-only, SSE streaming | | GPU Cloud | Modal.com (A10G + L4, $250 credits) | | Agent | ReAct loop, OpenAI function calling | | Testing | pytest (41 unit) + Playwright (13 E2E), all against live API | | Deployment | Hugging Face Spaces (Gradio) + Modal serverless | ## Links - ๐ŸŽฌ Demo video: https://www.youtube.com/watch?v=QN4ZL1Q_kNA - ๐Ÿฆ Social post: https://x.com/rockhighdev/status/2066432837075841399 ## License MIT