Building a RAG Pipeline with LLM Embeddings and Scikit-learn

In this article, you will learn how to build a lightweight, end-to-end RAG pipeline using scikit-learn for vector retrieval and open-source models for embeddings and text generation, without the use of paid APIs or heavyweight frameworks.

Topics we will cover include:

  • How to download a document dataset, chunk it into semantic pieces, and generate embeddings using a local sentence-transformer model.
  • How to build a custom retriever class using scikit-learn’s NearestNeighbors with cosine distance as a stand-in for a vector database.
  • How to wire the retriever together with a lightweight open-source LLM to produce a fully functional, in-memory RAG pipeline.

Building a RAG Pipeline with LLM Embeddings and Scikit-learn

Introduction

Modern retrieval augmented generation (RAG systems) are often thought of as inseparable from an expansive ecosystem of frameworks, including typically expensive, managed vector databases to store document collections for retrieval.

At the core, however, RAG systems rely on a fairly simple notion: calculating distances between semantic vectors representing texts. It’s not strictly necessary to navigate the intricacies of a dedicated AI infrastructure when working with a small-to-medium-sized corpus, prototyping a new proof-of-concept, or deploying to environments under cost constraints. Instead, we can use scikit-learn procedures together with open-source LLMs to build transparent, fast RAG pipelines that remain fully functional. This article shows how.

Step-by-Step Guide

The solution provided below is completely free to use, relying on sentence-transformers to build local embeddings from a text dataset and a lightweight pre-trained LLM from Hugging Face for the generation stage. If you need to brush up on basic RAG concepts, check out this article first.

While the pipeline can be implemented and run in a local IDE, for demonstration purposes I recommend running the entire pipeline on Google Colab, using its free T4 GPU for more efficient execution. If you follow this approach, start by installing and importing the required libraries and dependencies:

I made available a small dataset containing nine text files — brief descriptions of Asian countries — in a public GitHub repository. You can download it, extract the files, and save the texts in a simple list as follows:

The dataset we just loaded will constitute our miniature document base for RAG. We need to put it in the right format — that is, turn the texts into embedding vectors. Before doing that, it is common practice in RAG to chunk documents into smaller, semantic pieces that the embedding model — responsible for mapping pieces of text into numerical embeddings — can process more effectively. The texts in our dataset don’t really require chunking because they are quite short, but we are simulating this step to illustrate best practices in real-world RAG pipelines.

We define a native chunking function, using smaller-than-usual values for chunk size and overlap (both measured in words) so that we can observe some actual effect on our small documents:

Output:

In a real-world application, you will likely use significantly larger values for both arguments in the chunking function.

Next, we generate the embeddings using a popular lightweight model for this task: the 'all-MiniLM-L6-v2' sentence-transformer:

Once we have a collection of embeddings, it’s time to define one of the key components of any RAG pipeline: the retriever. Since we are doing this the scikit-learn way, we will wrap sklearn.neighbors.NearestNeighbors — a simple yet effective distance calculation algorithm — into a clean, reusable class that mimics the functionality of a vector database, all based on cosine distance, which is ideal for embedding vector representations.

The other major component of the pipeline is the generator. Here too we keep things lightweight, choosing a small, open-source LLM trained for natural language generation: Qwen/Qwen2.5-0.5B-Instruct. This model is small enough to run smoothly on a Colab notebook without risking a RAM crash.

All the pieces of the pipeline are now in place. The last step is to wire them together and try it out by asking our system a question about its knowledge base (Asian countries):

Output:

Try asking different questions by replacing the text in test_question. The behavior and outputs are reasonable given the small-scale setup we just built — though don’t expect commercial LLM-level results: we are combining a small model with a tiny knowledge base.

Final Remarks

In this article, we built a lightweight, end-to-end RAG pipeline that avoids the overhead of heavyweight frameworks or paid APIs. It relies solely on scikit-learn vector retrieval and open-source models for both embeddings and generation, producing a transparent, in-memory system. This approach makes a solid starting point for prototyping, experimenting with different retrieval strategies, and validating concepts before scaling up.

No comments yet.

Leave a Reply

Machine Learning Mastery is part of Guiding Tech Media, a leading digital media publisher focused on helping people figure out technology. Visit our corporate website to learn more about our mission and team.