Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CookRAG — Retrieval-Augmented Q&A for Cooking

A small microservice that answers cooking questions over a set of recipe and technique notes using Retrieval-Augmented Generation (RAG). Built with FastAPI, Google Gemini (embeddings + generation), and a lightweight local vector store.

I built this to get hands-on with the full RAG pipeline end to end: document ingestion, chunking, embedding, semantic retrieval, grounded generation, and serving it behind an API with per-request latency metrics. Cooking is just the content I picked; the pipeline is domain-agnostic, so you can point it at any document set by dropping files in data/.


What it does

Recipe and technique notes are scattered across files, and the answer to "why is my sear not browning?" or "how long do I rest a roast?" is buried somewhere in the text. CookRAG ingests those documents and exposes an /ask endpoint that returns a grounded, cited answer. The model answers only from retrieved passages, which reduces hallucination and keeps responses traceable to a source.

Architecture

                    +-------------+
   recipes/notes -> |  ingest.py  | chunk -> embed -> store
                    +-------------+
                           |
                           v
                    +-------------+
                    | vector store|  (numpy + cosine similarity, on disk)
                    +-------------+
                           ^
   user question -> /ask --+ embed query -> retrieve top-k -> build prompt
                           v
                    +-------------+
                    |   Gemini    |  grounded generation
                    +-------------+
                           |
                           v
                    cited answer + latency metrics

Tech

  • RAG: retrieval over a vector store, then grounded generation. No fine-tuning, which suits a knowledge-lookup task: cheaper, and no retraining when the documents change.
  • Embeddings: Gemini gemini-embedding-001 to vectorise chunks and queries.
  • Generation: Gemini gemini-2.5-flash.
  • Vector store: a numpy + cosine-similarity index persisted to disk. Dependency-light, and the retrieval interface is swappable for FAISS / Chroma / pgvector.
  • Service: FastAPI with request validation, structured error handling, retry-with-backoff on the LLM call, and per-request latency logging.

Design notes

  • Latency: total response time is embed query + vector search + LLM generation. The service times each stage separately (the /ask response includes a timing block). In practice generation dominates and retrieval is sub-millisecond at this scale, so the obvious next optimisation is streaming the response or using a smaller model.
  • Reliability: the LLM call is wrapped in exponential backoff (1s, 2s, 4s) to absorb transient 429/503 errors so a single rate-limit blip does not fail the request.
  • Chunking: chunks too large dilute retrieval relevance; too small lose context. CHUNK_SIZE and CHUNK_OVERLAP are configurable to tune this.
  • Grounding: the prompt instructs the model to answer only from the provided context and say so when the answer is not there. Retrieved sources are returned with each answer.
  • Cost & privacy: runs on Gemini's free tier. The free tier may use inputs for training, so only non-confidential content should go through it; the sample documents here are original. For sensitive data, a paid tier or Vertex AI avoids training on your inputs.

Setup

# 1. Install dependencies
pip install -r requirements.txt

# 2. Add your Gemini API key. Copy .env.example to .env and fill it in:
cp .env.example .env
#    then edit .env to set GEMINI_API_KEY=...
#    (free key, no card, at https://aistudio.google.com/apikey)

# 3. Sample cooking docs are already in data/. Add your own .txt or .pdf to extend it.

# 4. Ingest the documents (chunk -> embed -> store)
python -m scripts.ingest

# 5. Run the service
uvicorn app.main:app --reload

# 6. Ask a question
curl -X POST http://localhost:8000/ask \
  -H "Content-Type: application/json" \
  -d '{"question": "Why is my steak not browning when I sear it?"}'

Other questions to try:

  • "How long should I rest a roast chicken?"
  • "When should I salt meat before cooking?"
  • "How do I fix a broken vinaigrette?"
  • "Why salt the pasta water?"

Possible next steps

  • Stream responses so output appears as it is generated.
  • Swap the numpy store for FAISS or pgvector to scale past in-memory search.
  • Add evaluation: a set of question/expected-source pairs to measure retrieval quality.

About

A small RAG microservice that answers cooking questions over recipe and technique notes. FastAPI, Google Gemini for embeddings and generation, and a numpy vector store with per-request latency metrics.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages