Lab 11 — Managed RAG with a Bedrock Knowledge Base

Scaffold: 3/5. The first of the managed-track labs. Lab 05 made you write retrieval by hand; here the same documents go into a Knowledge Base and you write the two calls that query it.

The scenario

The Greenbox support assistant works, and the retrieval loop behind it is five documents held in memory, embedded on cold start, scored with a cosine function you wrote. That is fine for five documents and hopeless for five thousand: nothing re-embeds when a document changes, nothing chunks a long document into pieces small enough to retrieve usefully, and every cold start pays to embed the whole corpus again.

A Knowledge Base takes that job. It watches a bucket of documents, chunks them, embeds the chunks, keeps them in a vector index, and re-embeds only what changed when you sync. The same five topics are here, expanded into documents long enough that chunking matters, plus one that support staff can read and subscribers must not.

The requirement

What’s provided

Your task

In src/handler.py, fill the two gaps:

  1. retrieve(question, k, audience) — call Retrieve on bedrock-agent-runtime and reshape retrievalResults into {"text", "score", "source", "audience"} dicts. This is the raw search: no model, no prose, just chunks and scores.
  2. answer(question, k, audience) — call RetrieveAndGenerate, which does the same search and then writes an answer over the results. Return the text from output.text and the de-duplicated S3 URIs from citations[].retrievedReferences[].location.s3Location.uri.

Both pass their retrieval configuration through _vector_search_config(), so numberOfResults and the metadata filter are wired for you. The docstring has the exact request and response shapes.

Run it

# Prerequisite: Model access enabled for BOTH the generation model and the
# Titan embedding model, in your region.
./scripts/deploy.sh          # ~5 minutes the first time: the KB and index build
./scripts/test.sh
./scripts/teardown.sh

Defaults are stack genai-lab-11, region us-east-1, amazon.nova-lite-v1:0 for generation and amazon.titan-embed-text-v2:0 at 1024 dimensions for embedding. Override any of them with environment variables (STACK, AWS_REGION, MODEL_ID, EMBED_MODEL_ID, EMBED_DIMENSIONS, CHUNK_MAX_TOKENS, CHUNK_OVERLAP_PERCENTAGE).

What it costs. Small, and mostly one-off. Embedding five short documents is a fraction of a cent. S3 Vectors bills about USD$0.06 per GB-month of vectors and a per-query fee measured in dollars per million queries, so a few hundred vectors and a handful of test queries round to nothing. Nova Lite generation for the six test questions is well under a cent. The reason this lab uses S3 Vectors rather than OpenSearch Serverless is the shape of the bill: an OpenSearch Serverless collection charges for capacity units whether or not you query it, and forgetting to delete one is the expensive mistake in this track. Tear down when you finish anyway.

What success looks like

Before you fill the gaps, the function raises NotImplementedError. After:

Then change something. Edit docs/delivery-days.txt to add a Wednesday run, re-run ./scripts/deploy.sh, and ask again. The upload and the ingestion job are both in the deploy script, and Bedrock only re-embeds what changed.

If it fails

Reveal the solution

SRC=solution ./scripts/deploy.sh && ./scripts/test.sh

What you just learned

Next

Lab 12 — Fine-tune a model and read the loss curves. Retrieval fixes what the model does not know. Fine-tuning fixes how it answers: you prepare a training set, run a customisation job, and measure whether the tuned model is actually better than the prompt you already had.