Course Wiki
RAG Helper — LLM Zoomcamp Module 1
--- video_url: 'https://www.youtube.com/watch?v=JxaC6Hrym6c&list=PL3MmuxUbc_hLZFNgSad56pDBKK8KO0XIv' --- # RAG Helper
Related Pages
LLM Zoomcamp › Module 1: Agentic RAG › RAG Helper
Notes
video_url: “https://www.youtube.com/watch?v=JxaC6Hrym6c&list=PL3MmuxUbc_hLZFNgSad56pDBKK8KO0XIv”
RAG Helper
In the previous lessons, we built the RAG flow piece by piece - search, then the prompt, then the LLM call. The pipeline works, but every time we want to use it, we need to repeat the same code.
We’ll use this code throughout the course, so let’s put it into two reusable files:
- ingest.py - loading data and building the search index
- rag_helper.py - the RAG logic (search, prompt, LLM)
Then in notebooks, we just import from these files and use them.
ingest.py
This file handles data loading and index creation - everything we need before we can search.
Create ingest.py with two functions:
import requests
from minsearch import Index
def load_faq_data():
docs_url = "https://datatalks.club/faq/json/courses.json"
response = requests.get(docs_url)
courses_raw = response.json()
documents = []
url_prefix = "https://datatalks.club/faq"
for course in courses_raw:
course_url = f"""{url_prefix}{course["path"]}"""
course_response = requests.get(course_url)
course_response.raise_for_status()
course_data = course_response.json()
documents.extend(course_data)
return documents
def build_index(documents):
index = Index(
text_fields=["question", "section", "answer"],
keyword_fields=["course"]
)
index.fit(documents)
return index
We’ll use load_faq_data() to fetch the documents and build_index()
to create the minsearch index. Later, we’ll add sqlitesearch support
to this same file.
rag_helper.py
This file contains the RAG logic - the same functions we wrote in the previous lessons, now organized as a class.
We use a class because index and openai_client are currently global
variables. Move the functions to a separate file and those globals
aren’t there anymore. We could import them back, but that ties the file
to one specific index and one specific client. That makes the code hard
to reuse and adjust.
So we put the dependencies inside a class instead. The index and the LLM client become constructor arguments. Now we can pass any index or client we want when we create the object. And because it’s a class, we can subclass it later to override one piece without touching the rest. For example, we can swap OpenAI for a local model.
Create rag_helper.py:
INSTRUCTIONS = """
Your task is to answer questions from the course participants
based on the provided context.
Use the context to find relevant information and provide accurate
answers. If the answer is not found in the context,
respond with "I don't know."
"""
PROMPT_TEMPLATE = """
QUESTION: {question}
CONTEXT:
{context}
""".strip()
Now the class: RAGBase
class RAGBase:
def __init__(
self,
index,
llm_client,
instructions=INSTRUCTIONS,
prompt_template=PROMPT_TEMPLATE,
course="llm-zoomcamp",
model="gpt-5.4-mini"
):
self.index = index
self.llm_client = llm_client
self.instructions = instructions
self.course = course
self.prompt_template = prompt_template
self.model = model
The index parameter is anything with a search method, whether
minsearch, sqlitesearch, or something else. The other four parameters
all have defaults. You only pass course, instructions,
prompt_template, or model when you want to override the default
behavior. We swap the index later without touching any of the RAG code.
The search method delegates to the index:
def search(self, query, num_results=5):
boost_dict = {"question": 3.0, "section": 0.5}
filter_dict = {"course": self.course}
return self.index.search(
query,
num_results=num_results,
boost_dict=boost_dict,
filter_dict=filter_dict
)
The build_context
Key concepts
Related notes
- llmz-m01-agents
- llmz-m01-building-the-prompt
- llmz-m01-data-ingestion
- llmz-m01-environment
- llmz-m01-function-calling
- llmz-m01-introduction
- llmz-m01-other-frameworks
- llmz-m01-quick-rag-revision-optional
- llmz-m01-rag
- 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-2
- llmz-m02-vector-search-with-minsearch
- 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-best-practices
- llmz-m03-context-engineering
- llmz-m03-multi-agent-systems
- llmz-m03-next-steps
- llmz-m03-retrieval-augmented-generation
- llmz-m03-setting-up-kestra
- llmz-m04-agent-evaluation
- llmz-m04-evaluation
- llmz-m04-generating-ground-truth-data
- 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-parameter-tuning
- llmz-m05-assistant
- llmz-m05-built-in-judge
- llmz-m05-capturing-metrics
- llmz-m05-chat-app
- llmz-m05-docker-compose
- llmz-m05-monitoring
- llmz-m05-next-steps
- llmz-m05-querying-data
- llmz-m05-storing-data-in-postgresql
- llmz-m05-streamlit-dashboard
- llmz-m05-synthetic-data-generation
- llmz-m05-user-feedback
- llmz-m06-best-practices-for-rag
- llmz-m06-hybrid-search
- llmz-m06-hybrid-search-with-langchain
- llmz-m06-next-steps
- 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