Tell me for any kind of development solution

Edit Template

Building RAG Systems with Open-Source Tools: A Step-by-Step Guide

Building RAG (Retrieval-Augmented Generation) Systems with Open-Source Tools is transforming how we enhance large language models (LLMs) with precise, context-driven responses. By combining retrieval mechanisms with generative AI, RAG systems fetch relevant information from external sources, reducing errors like hallucinations and delivering accurate, up-to-date answers. 

This article provides a comprehensive guide to creating a RAG system using open-source libraries such as LangChain, Faiss, and Hugging Face models. Aimed at developers, researchers, and AI enthusiasts, it addresses pain points like slow performance, complex document handling, and high costs, offering actionable steps and code snippets to build a cost-effective, customizable solution at a Grade 8–10 reading level.

Why RAG is a Game-Changer

Traditional LLMs rely on static training data, which can become outdated or lack specific context for specialized domains. Building RAG (Retrieval-Augmented Generation) Systems with Open-Source Tools solves this by integrating real-time data retrieval, enabling responses that are more accurate and relevant. This approach is perfect for applications like Q&A chatbots, customer support systems, or personal knowledge bases, where precision is critical. Open-source tools make it affordable, transparent, and highly customizable, eliminating the need for expensive API dependencies.


Core Components of a RAG System

A RAG system operates in two main phases: indexing and retrieval-generation. Here’s a breakdown of the key components:

  • Document Processing: Splits large datasets into smaller chunks for efficient retrieval.
  • Embedding Generation: Converts text into vectors capturing semantic meaning.
  • Vector Store: Stores embeddings for fast similarity searches.
  • Retrieval: Fetches relevant chunks based on user queries.
  • Response Generation: Uses an LLM to synthesize retrieved data into coherent answers.

These components work together to ensure fast, accurate responses, making Building RAG (Retrieval-Augmented Generation) Systems with Open-Source Tools a powerful solution for context-driven AI.


Step-by-Step Guide to Building a RAG System

Let’s build a RAG system for a Q&A application using a blog post by Lilian Weng on LLM-powered agents as our data source. We’ll use open-source tools like LangChain, Faiss, and Hugging Face models, with code snippets and time-saving tips to streamline the process.

Step 1: Setting Up Your Environment

Begin by installing the necessary open-source libraries to keep your setup cost-free and flexible.

pip install --quiet langchain langchain-community langchain-text-splitters faiss-cpu
pip install -qU langchain-huggingface

These commands install LangChain for orchestration, Faiss for vector storage, and Hugging Face embeddings for semantic search. Time-Saving Tip: Use Poetry (poetry install) to manage dependencies in a virtual environment, avoiding conflicts and speeding up setup.

Step 2: Data Preparation and Indexing

Indexing involves loading, chunking, and storing data for efficient retrieval. Here’s how to do it:

Load Data: Use LangChain’s WebBaseLoader to fetch content from a URL, filtering for relevant sections to reduce noise.

import bs4
from langchain_community.document_loaders import WebBaseLoader

bs4_strainer = bs4.SoupStrainer(class_=("post-title", "post-header", "post-content"))
loader = WebBaseLoader(
    web_paths=("https://lilianweng.github.io/posts/2023-06-23-agent/",),
    bs_kwargs={"parse_only": bs4_strainer},
)
docs = loader.load()

Chunk Text: Split the document into smaller pieces to fit LLM context windows and improve retrieval accuracy. Use RecursiveCharacterTextSplitter for intelligent splitting at logical breaks like paragraphs.

from langchain_text_splitters import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
all_splits = text_splitter.split_documents(docs)

Time-Saving Tip: Set chunk_overlap=200 to preserve context across chunk boundaries, reducing the need for manual adjustments later.

Embed and Store: Convert chunks into embeddings using Hugging Face’s nomic-embed-text model and store them in a Faiss vector database for fast similarity searches.

from langchain_community.vectorstores import FAISS
from langchain_huggingface import HuggingFaceEmbeddings

embedding = HuggingFaceEmbeddings(model_name="nomic-embed-text")
db = FAISS.from_documents(all_splits, embedding)
db.save_local('faiss_index')

This creates a reusable index you can load later, saving time by avoiding reprocessing in production environments.

Step 3: Retrieval and Generation Pipeline

The retrieval-generation pipeline is the core of Building RAG (Retrieval-Augmented Generation) Systems with Open-Source Tools, combining search and LLM capabilities to deliver answers.

Retrieve Relevant Chunks: Use Faiss to perform similarity searches based on the user’s query.

def retrieve(question):
    new_db = FAISS.load_local("faiss_index", embedding, allow_dangerous_deserialization=True)
    return new_db.similarity_search(question, k=4)

Generate Responses: Pass retrieved chunks to an LLM like phi3 from Ollama for concise, context-grounded answers.

from langchain_community.llms import Ollama

def generate_response(question, context):
    context_text = "\n\n".join(doc.page_content for doc in context)
    prompt = f"""
    You are a helpful assistant. Use the following context to answer the question concisely:
    Context: {context_text}
    Question: {question}
    Answer in 3 sentences or less.
    """
    model = Ollama(model='phi3')
    response = model.invoke(prompt)
    return response

Example Usage:

question = "What is Task Decomposition?"
context = retrieve(question)
answer = generate_response(question, context)
print(answer)

Output Example: Task decomposition breaks complex tasks into smaller, manageable steps to enhance problem-solving efficiency. Techniques like Chain of Thought (CoT) and Tree of Thoughts guide models to reason step-by-step. It can be initiated via simple prompts, task-specific instructions, or human inputs.

Step 4: Optimizing for Performance

Building RAG (Retrieval-Augmented Generation) Systems with Open-Source Tools can face challenges like low retrieval precision, high latency, or irrelevant results. Here are optimizations to address them:

  • Context-Aware Chunking: Use NLP techniques to split text at logical breaks (e.g., paragraphs or topic shifts) instead of fixed sizes, preserving context and boosting retrieval accuracy.
  • Reranking Models: Add a reranking step using models like Hugging Face’s cross-encoder to refine retrieved documents, improving precision without significantly increasing latency.
  • Adaptive Batching: Use BentoML’s adaptive batching to optimize inference requests, achieving up to 3x lower latency and 2x higher throughput compared to non-batched setups.
  • Metadata Filtering: Add metadata (e.g., document section) to chunks for targeted retrieval, enhancing relevance.

Example Metadata Filtering:

for i, doc in enumerate(all_splits):
    doc.metadata["section"] = "beginning" if i < len(all_splits)//3 else "middle" if i < 2*len(all_splits)//3 else "end"
db = FAISS.from_documents(all_splits, embedding)

This enables queries like “What does the end of the post say about Task Decomposition?” to target specific sections, improving response relevance.

Step 5: Adding Conversational Awareness

To create a chatbot-like experience, incorporate conversation history to contextualize follow-up questions. For example, transform “What’s the cost?” into “What’s the cost of laundry service?” based on prior exchanges.

def contextualize_query(current_query, history):
    prompt = f"""
    Given the conversation history: {history}
    Rewrite this query to include relevant context: {current_query}
    """
    model = Ollama(model='phi3')
    return model.invoke(prompt)

Time-Saving Tip: Store conversation history in a simple in-memory list or dictionary to avoid redundant processing, ensuring quick responses in chat applications.

Step 6: Handling Complex Documents

Real-world data often includes complex formats like PDFs, websites, or tables. Enhance your RAG system with:

  • Layout Analysis: Use LayoutLMv3 for layout-aware parsing of structured documents, improving accuracy for content with images or tables.
  • Table Extraction: Employ Table Transformer (TATR) to detect and extract table data accurately, ideal for financial reports or product specs.
  • Document Q&A: Integrate Donut or LayoutLMv3 for visual question-answering, enabling queries over mixed text-image content.

These tools ensure your system handles diverse data types, a critical aspect of Building RAG (Retrieval-Augmented Generation) Systems with Open-Source Tools.

Step 7: Scaling with BentoML

For production, scaling RAG systems is essential. BentoML simplifies this with:

  • Adaptive Batching: Dynamically adjusts batch sizes to optimize throughput, reducing latency by up to 3x.
  • Model Composition: Combines multiple models (e.g., embedding, LLM, reranker) into a single pipeline for streamlined deployment.
  • GPU Scaling: Uses concurrency-based autoscaling to maximize GPU utilization, handling high-throughput workloads efficiently.

Example BentoML Setup:

import bentoml
from langchain_community.vectorstores import FAISS
from langchain_huggingface import HuggingFaceEmbeddings

@bentoml.service
class RAGService:
    def __init__(self):
        self.embedding = HuggingFaceEmbeddings(model_name="nomic-embed-text")
        self.db = FAISS.load_local("faiss_index", self.embedding, allow_dangerous_deserialization=True)

    @bentoml.api
    def query(self, question: str) -> str:
        context = self.db.similarity_search(question, k=3)
        context_text = "\n\n".join(doc.page_content for doc in context)
        # Add LLM inference here
        return context_text

This setup ensures efficient scaling and resource utilization for production environments.


Example Implementation: Hotel Q&A Bot

Here’s a complete, minimal implementation for a hotel Q&A bot, combining all steps:

import bs4
from langchain_community.document_loaders import WebBaseLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import FAISS
from langchain_community.llms import Ollama
from langchain_huggingface import HuggingFaceEmbeddings

# Load and index hotel data
loader = WebBaseLoader("https://example-hotel.com/policies")
docs = loader.load()
text_splitter = RecursiveCharacterTextSplitter(chunk_size=750, chunk_overlap=150)
splits = text_splitter.split_documents(docs)
embedding = HuggingFaceEmbeddings(model_name="nomic-embed-text")
db = FAISS.from_documents(splits, embedding)
db.save_local('hotel_index')

# Query handling
def answer_query(question):
    db = FAISS.load_local("hotel_index", embedding, allow_dangerous_deserialization=True)
    context = db.similarity_search(question, k=3)
    context_text = "\n\n".join(doc.page_content for doc in context)
    prompt = f"Answer based on this context: {context_text}\nQuestion: {question}"
    model = Ollama(model='phi3')
    return model.invoke(prompt)

# Test
print(answer_query("What are the check-in times?"))

This 50-line implementation creates a functional RAG system, ideal for prototyping or small-scale projects.


Deploying Your RAG System

Deploying your RAG system ensures it’s accessible to users. Building RAG (Retrieval-Augmented Generation) Systems with Open-Source Tools shines in deployment flexibility, especially with tools like Streamlit and BentoML.

Streamlit for Quick UI: Create a user-friendly interface with Streamlit to allow real-time interaction.

pip install streamlit
streamlit run app.py

Example Streamlit App:

import streamlit as st
from langchain_community.vectorstores import FAISS
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_community.llms import Ollama

st.title("Hotel Q&A Bot")
embedding = HuggingFaceEmbeddings(model_name="nomic-embed-text")
db = FAISS.load_local("hotel_index", embedding, allow_dangerous_deserialization=True)

question = st.text_input("Ask a question about the hotel:")
if question:
    context = db.similarity_search(question, k=3)
    context_text = "\n\n".join(doc.page_content for doc in context)
    prompt = f"Answer based on this context: {context_text}\nQuestion: {question}"
    model = Ollama(model='phi3')
    response = model.invoke(prompt)
    st.write(response)

Time-Saving Tip: Use Streamlit’s caching (@st.cache_resource) to load the Faiss index once, reducing startup time.

BentoML for Production: Deploy to production with BentoML for scalability and monitoring.

bentoml deploy RAGService:latest

BentoML’s BentoCloud offers observability features like tracing and logging, helping you monitor performance in real-time.


Evaluating RAG Performance

Evaluating your RAG system ensures it meets user expectations. Key metrics include:

  • Recall: Measures if all relevant chunks are retrieved.
  • Precision: Ensures retrieved chunks are relevant to the query.
  • Response Quality: Assesses if answers are coherent and accurate.

Synthetic Dataset Creation: Use an LLM to generate evaluation datasets.

def create_eval_dataset(question, context, model):
    prompt = f"Generate 5 similar questions based on this context: {context}"
    similar_questions = model.invoke(prompt)
    return similar_questions.split("\n")

LLM as Evaluator: Use an LLM to score response quality.

def evaluate_response(question, response, model):
    prompt = f"Score this response (0-10) for relevance and coherence: Question: {question}, Response: {response}"
    score = model.invoke(prompt)
    return score

Time-Saving Tip: Automate evaluation with LangSmith for tracing and debugging, reducing manual effort. Learn more at LangSmith Documentation.


Advanced Techniques: Cross-Modal Retrieval

To take Building RAG (Retrieval-Augmented Generation) Systems with Open-Source Tools to the next level, explore cross-modal retrieval, which integrates text, images, and audio. Models like ImageBind enable this by creating a shared embedding space.

Example Use Case: A hotel Q&A bot that retrieves answers from text policies and images of amenities (e.g., “Show the pool area”).

from imagebind import ImageBindModel

model = ImageBindModel()
image_embedding = model.embed_image("pool.jpg")
text_embedding = model.embed_text("What does the pool look like?")
similarity = model.cosine_similarity(image_embedding, text_embedding)

This approach enhances your RAG system’s versatility, handling multimedia queries effectively.


Practical Next Steps

To continue Building RAG (Retrieval-Augmented Generation) Systems with Open-Source Tools:

  • Experiment with Models: Try smaller models like phi3-mini for faster inference or fine-tune nomic-embed-text on your domain.
  • Expand Data Sources: Include PDFs, emails, or databases using PyPDFLoader or SQLLoader.
  • Contribute to Open Source: Fork projects like StepByStep-RAG and share improvements.
  • Monitor and Iterate: Use BentoCloud’s observability to track performance and refine your system.

Use Cases for RAG Systems

RAG systems are versatile and can be applied to:

  • Internal Documentation: Query company manuals or wikis with high accuracy, streamlining employee workflows.
  • Educational Tools: Build study aids that answer questions based on textbooks or lecture notes, aiding students.
  • Customer Support: Create chatbots that reference FAQs or product manuals, improving response times.
  • Personal Knowledge Bases: Organize and query research papers or personal notes for quick insights.

For example, a hotel Q&A bot could retrieve check-in times or amenities from a hotel’s policy page, delivering precise answers to guest queries.


Overcoming Common Challenges

RAG systems face challenges that can impact performance. Here’s how to address them:

  • Low Retrieval Precision: Fine-tune embedding models on domain-specific data to improve relevance.
  • Complex Documents: Use layout-aware models like LayoutLMv3 to parse structured data accurately.
  • High Latency: Deploy smaller models or use BentoML’s adaptive batching for faster inference.
  • Data Quality: Preprocess data with Pandas to clean and filter irrelevant content.

Time-Saving Shortcuts

To streamline Building RAG (Retrieval-Augmented Generation) Systems with Open-Source Tools:

  • Use pre-trained models like nomic-embed-text to skip training.
  • Save Faiss indexes locally (db.save_local(‘faiss_index’)) to avoid re-indexing.
  • Pull pre-built prompts from LangChain’s hub: hub.pull(“rlm/rag-prompt”).
  • Deploy a quick UI with Streamlit: streamlit run app.py.

Useful Resources

  • LangChain Documentation for detailed guides on RAG components.
  • Hugging Face Hub for open-source models like nomic-embed-text.
  • BentoML Tutorials for scaling and deploying RAG systems.
  • Faiss GitHub for vector store documentation.

Conclusion

Building RAG (Retrieval-Augmented Generation) Systems with Open-Source Tools empowers you to create accurate, context-aware AI applications without costly APIs. By leveraging LangChain, Faiss, Hugging Face models, and BentoML, you can build modular, scalable systems tailored to your needs. This guide provides a clear path from setup to deployment, addressing challenges like performance and complex data handling with practical solutions. Experiment with the code, explore advanced techniques, and contribute to open-source projects to unlock the full potential of RAG. Start building today and transform your AI projects!


FAQs

1. What is a RAG system, and why use open-source tools?

A RAG system retrieves relevant data and generates AI responses for accurate, context-rich answers. Building RAG (Retrieval-Augmented Generation) Systems with Open-Source Tools is cost-effective, customizable, and transparent, allowing you to avoid expensive APIs. Open-source libraries like LangChain and Faiss enable tailored solutions for applications like chatbots or knowledge bases without compromising control.

2. Which open-source tools are best for building a RAG system?

Top tools include LangChain for workflow orchestration, Faiss for vector storage, and Hugging Face models like nomic-embed-text for embeddings. Ollama’s phi3 is great for lightweight response generation. These tools make Building RAG (Retrieval-Augmented Generation) Systems with Open-Source Tools scalable, efficient, and accessible for projects like Q&A bots or support systems.

3. How do I start building a RAG system with open-source tools?

Install libraries like LangChain and Faiss, load data with WebBaseLoader, chunk it using RecursiveCharacterTextSplitter, and store embeddings in a Faiss database. Set up retrieval and generation with models like phi3. Follow a guide on Building RAG (Retrieval-Augmented Generation) Systems with Open-Source Tools to streamline indexing, retrieval, and response generation for quick setup.

4. Can I build a RAG system without a GPU?

Yes, CPU-based tools like Faiss and lightweight models like phi3 from Ollama work well. Building RAG (Retrieval-Augmented Generation) Systems with Open-Source Tools on a CPU is ideal for prototyping or small-scale projects. For larger datasets, consider cloud-based GPUs, but CPUs suffice for most initial implementations, keeping costs low.

5. How do I improve the accuracy of a RAG system?

Enhance accuracy with context-aware chunking, reranking models like cross-encoder, and metadata filtering. Fine-tune embeddings on domain-specific data for better relevance. These optimizations in Building RAG (Retrieval-Augmented Generation) Systems with Open-Source Tools ensure retrieved chunks are precise, reducing irrelevant responses and improving user satisfaction.

6. What are common uses for RAG systems?

RAG systems power Q&A chatbots, customer support tools, educational aids, and personal knowledge bases. For example, a hotel bot can answer guest queries using policy documents. Building RAG (Retrieval-Augmented Generation) Systems with Open-Source Tools enables accurate, context-driven applications for querying manuals, FAQs, or research papers efficiently.

Share Article:

© 2025 Created by ArtisansTech