
Quick overview of core code (abbreviated)
These helper functions are used throughout the examples below.Simple interactive test — mixed corpus
Run the interactive test against the hybrid retriever (vectors + BM25):Re-ingest only Sherlock Holmes
Reset the vector DB and re-ingest a single book to narrow retrieval scope:Testing character and setting questions
- Some direct fact questions work well (e.g., identifying Scotland Yard inspectors).
- Other queries are sensitive to phrasing. Example: the query
What is Holmes' address?initially returned “I don’t know.” Rephrasing produced the expected result.
Key knobs to tune (what they do and why they matter)
Use these controls to influence retrieval and final LLM prompt composition.Tips for tuning:
- Start with small
k_eachandfinal_kfor fast iteration; increase if you need more candidate evidence. - Adjust
chunk_sizeandoverlapper document type (narrative vs. technical). - Always re-ingest after changing chunking parameters.
Reciprocal Rank Fusion (RRf) — merging ranked lists
We used RRf to merge BM25 and vector ranking lists. This is a simple but effective fusion technique:Chunking implementation
A simple chunker used when ingesting plain text documents:chunk_size or overlap, you must re-ingest the corpus for changes to take effect.
CLI options for runtime tuning
The script exposes flags to tune retrieval at query time.k_each and final_k provides the LLM with more context but does not guarantee a correct answer. Often phrasing or chunking changes are necessary.
Testing methodology — query categories to run
Use a consistent test suite that includes:- Known-answer queries: verify correct retrieval and supporting chunks.
- Paraphrase/rephrasing: test semantic robustness.
- Out-of-corpus queries: check that the system abstains instead of hallucinating.
- Ambiguous/referential questions: ensure the system either clarifies, anchors, or abstains.
Dealing with ambiguity and partial support
If the LLM returns partial or uncertain answers:- Add anchors in the query (story title, character name).
- Increase
k_eachandfinal_kto add more evidence. - Tune chunking at ingestion to ensure relevant facts are grouped.
- Use synonyms and paraphrases in tests to probe retrieval sensitivity.
Ingestion tuning — practical tip
Chunk size and overlap are applied at ingestion time. To experiment:Changing chunking parameters requires re-ingesting the data and resetting the vector store (e.g., Chroma). Always backup or version your embeddings/database before resetting.
Testing summary and next steps
- Create a test suite with known answers, paraphrases, ambiguous, and out-of-corpus queries.
- Use that suite to evaluate whether the system retrieves relevant chunks, abstains appropriately, or hallucinates.
- Iterate on ingestion (chunking), retrieval budgets (
k_each,final_k), reranking/fusion strategy (e.g., RRf), and prompt templates. - Compare results across embedding models and LLMs to determine the best combination for your corpus and use case.
Testing approach summary:
- Create a suite of queries that includes known facts, paraphrases, ambiguous questions, and clearly out-of-corpus questions.
- Use these to evaluate whether the system retrieves relevant context, abstains properly, or hallucinates.
- Tune ingestion (chunk_size, overlap) and retrieval (k_each, final_k) and compare results.
Final notes and references
- RAG systems reduce hallucination risk by grounding answers in retrieved context, but they remain sensitive to retrieval quality, chunking strategy, and prompt engineering.
- Use the testing methodology above to find failure modes, then iterate on ingestion, retrieval budgets, reranking, and prompts.
- The full example code and repository for this lesson are included with the course materials — reproduce, tune, and extend the pipeline with your own data.
- Retrieval-Augmented Generation (RAG) overview
- Chroma DB: https://www.trychroma.com/
- BM25 / rank_bm25: https://pypi.org/project/rank-bm25/
- Reciprocal Rank Fusion (RRf): original literature and implementations