Course Wiki
Generating Ground Truth Data — LLM Zoomcamp Module 4
--- video_url: 'https://www.youtube.com/watch?v=YScoH28cVf8&list=PL3MmuxUbc_hLZFNgSad56pDBKK8KO0XIv' --- # Generating Ground Truth Data
Related Pages
LLM Zoomcamp › Module 4: Evaluation › Generating Ground Truth Data
Notes
video_url: “https://www.youtube.com/watch?v=YScoH28cVf8&list=PL3MmuxUbc_hLZFNgSad56pDBKK8KO0XIv”
Generating Ground Truth Data
To evaluate search, we need a dataset of queries where we know which document is the correct answer. This is called ground truth (or gold standard) data.
For each query in our ground truth dataset, we know which document in the knowledge base is relevant. When we run a search, we check whether the results include the correct document.
There are several ways to get ground truth data:
- Human annotators look at documents and write queries (best quality, expensive)
- Collect real user queries and label them (requires a running system)
- Generate synthetic data with an LLM (what we’ll do)
We don’t have a production system yet, so we’ll use an LLM to generate questions. For each FAQ document, we ask the LLM to create 5 questions that this document would answer. Then we know that for each generated question, the source document is the correct answer.
Loading the documents
We’ll use helper files from module 01 and this module.
If you don’t have them in your notebook directory, download them:
PREFIX=https://raw.githubusercontent.com/DataTalksClub/llm-zoomcamp/main
wget ${PREFIX}/cohorts/2026/01-agentic-rag/code/ingest.py
wget ${PREFIX}/cohorts/2026/01-agentic-rag/code/rag_helper.py
wget ${PREFIX}/cohorts/2026/04-evaluation/code/evaluation_utils.py
Then load the FAQ data:
from ingest import load_faq_data
documents = load_faq_data()
We’ll generate questions only for the LLM Zoomcamp FAQ. The full FAQ dataset contains documents from multiple courses. Generating five questions for every document would take longer and cost more.
documents_llm = []
for doc in documents:
if doc["course"] == "llm-zoomcamp":
documents_llm.append(doc)
len(documents_llm)
We’ll use these documents from now on so let’s name them as documents
documents = documents_llm
Each document already has an id field:
doc = documents[0]
print(doc["id"])
print(doc["question"])
print(doc["answer"])
The ID becomes the label in our ground truth dataset. We generate questions from a document, so we know that this document holds the answer. Later, search evaluation checks whether search brings back the document with this ID.
This is why every record needs a stable ID. If you can’t uniquely identify a document, you can’t tell whether search retrieved the right one. When you build your own evaluation set, assign an ID to each record in your knowledge base first.
Generating questions with structured output
We use an LLM to generate questions for each document.
This is the first time we’re using structured output in the course.
With structured output, we ask the LLM to return data in a specific
format instead of free-form text. For example, instead of getting a
paragraph that contains questions, we can ask for a Python object with
a questions field.
This is useful when code will process the output. The model returns the same structure every time. We can access the generated questions directly instead of parsing text manually.
We want the output as a list of strings, so we define that structure with a Pydantic model:
from pydantic import BaseModel
class Questions(BaseModel):
questions: list[str]
The instructions for the LLM:
data_gen_instructions = """
You emulate a student who's taking our course.
Formulate 5 questions this student might ask based on a FAQ record. The record
should contain the answer to the questions, and the questions should be complete and not too short.
If possible, use as fewer words as possible from the record.
The output should resemble how people ask questions
on the internet. Not too formal, not too short, not too long.
""".strip()
We ask the LLM to use different wording from the original document. This makes the evaluation more realistic - real users won’t phrase their ques
Key concepts
Related notes
- llmz-m01-building-the-prompt
- llmz-m01-data-ingestion
- llmz-m01-environment
- llmz-m01-function-calling
- llmz-m01-other-frameworks
- llmz-m01-quick-rag-revision-optional
- llmz-m01-rag
- llmz-m01-rag-helper
- llmz-m01-search
- llmz-m01-the-agentic-loop
- llmz-m01-the-course-faq-dataset
- llmz-m01-the-llm
- llmz-m01-toyaikit
- llmz-m01-wrap-up-of-part-1
- llmz-m02-embeddings
- llmz-m02-next-steps
- llmz-m02-rag-with-vector-search
- llmz-m02-using-onnx-runtime-instead-of-pytorch
- llmz-m02-vector-search
- llmz-m02-vector-search-with-pgvector
- llmz-m02-vector-search-with-sqlitesearch
- llmz-m03-ai-agents
- llmz-m03-ai-copilot
- llmz-m03-ai-orchestration
- llmz-m03-context-engineering
- llmz-m03-retrieval-augmented-generation
- llmz-m03-setting-up-kestra
- llmz-m04-agent-evaluation
- llmz-m04-evaluation
- llmz-m04-generating-ground-truth-for-all-documents
- llmz-m04-generating-rag-answers
- llmz-m04-llm-as-a-judge
- llmz-m04-next-steps
- llmz-m04-rag-and-agent-evaluation
- llmz-m04-search-evaluation
- llmz-m04-search-evaluation-metrics
- llmz-m04-search-parameter-tuning
- llmz-m05-assistant
- llmz-m05-built-in-judge
- llmz-m05-capturing-metrics
- llmz-m05-monitoring
- llmz-m05-next-steps
- llmz-m05-querying-data
- llmz-m05-storing-data-in-postgresql
- llmz-m05-streamlit-dashboard
- llmz-m05-user-feedback
- llmz-m06-best-practices-for-rag
- llmz-m06-document-reranking
- llmz-m06-hybrid-search-with-langchain
- llmz-m07-chunking-for-longer-texts
- llmz-m07-content-processing-cases-and-steps
- llmz-m07-end-to-end-project-example
- llmz-m07-evaluating-rag
- llmz-m07-evaluating-retrieval
- llmz-m07-interface-and-ingestion-pipeline
- llmz-m07-monitoring-and-containerization
- llmz-m07-summary-and-closing-remarks