Step 1: Stand up the assistant and feel the blind spot
You inherit the Northwind Cloud support assistant. It is a small but real Retrieval-Augmented Generation (RAG) service: eight knowledge-base documents, chunked and embedded with an NVIDIA embedding model through the in-cluster proxy, stored in a Milvus vector store, retrieved by cosine similarity, and turned into an answer by a chat model behind the same proxy.
It works. Ask it how to reset a password and it tells you. What it cannot tell you is anything about itself: how long a request took, whether the time went to retrieval or to the model, how many tokens the model consumed, what a day of traffic costs, or which of today's answers were wrong. Every one of those questions arrives eventually, usually from finance or from an angry customer, and today the only honest answer is "we don't know".
That gap is what observability closes, and this lab has you close it by hand. Before instrumenting anything, run the service and read the code you are about to instrument.
do this
1. Build the index and answer the question set. Click Run. The first
command embeds the knowledge base and writes the Milvus collection to
/home/labuser/kb.db. The second answers the six questions in
questions.jsonl, prints each answer with the documents it retrieved, and
writes answers.jsonl.
2. Read app.py top to bottom. Three functions matter for the rest of the
lab:
retrieve(question)embeds the question and runs a top-k vector search. It returns chunks with their cosine scores.generate(question, hits)builds the prompt from the retrieved chunks and calls the chat model. The API response carries ausageblock with the real prompt and completion token counts.answer(question)is the request end to end: retrieve, then generate.
Notice the with TRACER.span(...) lines already wrapped around each of them.
Those are the instrumentation points. They call into tracer.py, which right
now is a stub that records nothing. app.py decides where the spans are;
tracer.py decides what is recorded, redacted, kept and priced. Keeping
those two decisions in separate files is the first design choice of an
observability layer, because the call sites rarely change and the policy
changes every quarter.
3. Look at answers.jsonl. It has the answer and the sources for each
question and nothing else. No timing, no tokens, no cost, no trace id. That
is the blind spot you are about to remove.
Why this matters in practice
Teams typically add observability after the first incident, when it is too late to know what normal looked like. The order in this lab is the order that works: instrument first, so the baseline exists before anyone needs it.
provided for you:cost.pykb_account-deletion.mdkb_api-keys.mdkb_billing.mdkb_data-export.mdkb_getting-started.mdkb_regions.mdkb_sso.mdkb_status-incidents.mdpricing.yamlquestions.jsonltracer.py