How to Build a RAG Pipeline with Open Source Tools: A Practical Guide
A step-by-step guide to building a retrieval-augmented generation pipeline using open source tools like LangChain, Chroma, and LlamaIndex. Includes trade-offs, failure modes, and source-backed recommendations.


Retrieval-augmented generation (RAG) has become the standard architecture for grounding large language model outputs in your own data. By combining a retrieval step with a generation step, RAG reduces hallucinations and makes answers verifiable. This guide walks through building a production-style RAG pipeline using only open source components, with practical decisions, trade-offs, and failure modes.
When to Use a RAG Pipeline
Use RAG when you need to answer questions from a private or domain-specific document collection without retraining the LLM. Typical use cases:
- Internal knowledge bases for customer support
- Legal or compliance document Q&A
- Technical documentation assistants
- Research paper summarization
RAG works best when the retrieval corpus is relatively static or changes infrequently, and when latency of a few seconds is acceptable.
When to Avoid RAG
Avoid RAG in these scenarios:
- Real-time chat with low latency requirements – the retrieval step adds 200–1000 ms. For sub-second responses, consider fine-tuning or a smaller model.
- Very small or static knowledge – if you only have a handful of documents, prompt engineering or in-context learning may suffice.
- Highly dynamic data – if documents change every minute, the ingestion pipeline becomes a maintenance burden. Consider a vector store that supports incremental updates (e.g., Qdrant) but accept higher complexity.
Source-Backed Comparison: Vector Database Options
The vector store is the heart of the retrieval step. The table below compares four open source options.
| Vector DB | Index Type | GPU Support | Hybrid Search | Official Docs |
|---|---|---|---|---|
| Chroma | HNSW | No | No | [docs.trychroma.com](https://docs.trychroma.com/) |
| FAISS | IVF, HNSW, flat | Yes (via CUDA) | No | [github.com/facebookresearch/faiss](https://github.com/facebookresearch/faiss) |
| Qdrant | HNSW | No | Yes (BM25) | [qdrant.tech/documentation](https://qdrant.tech/documentation/) |
| Weaviate | HNSW | No | Yes (vector + keyword) | [weaviate.io/developers](https://weaviate.io/developers) |
Note: FAISS does not provide a built-in storage layer; you must manage persistence separately. Chroma is the easiest to get started with but lacks hybrid search. Qdrant and Weaviate offer richer query capabilities.
Practical Workflow: Step-by-Step
Document Ingestion
– Chunk documents into overlapping segments (e.g., 512 tokens with 128 token overlap). Use a text splitter from LangChain or LlamaIndex.
– Store original metadata (source file, page number, timestamp) alongside each chunk.
Embedding Generation
– Use an open embedding model like `BAAI/bge-small-en-v1.5` or `sentence-transformers/all-MiniLM-L6-v2`.
– Run embeddings on CPU or GPU. For large corpora, batch processing is essential.
Indexing
– Insert embeddings and metadata into your chosen vector store.
– Configure a distance metric (cosine or dot product). Cosine is recommended for normalized embeddings.
Retrieval
– At query time, embed the user question with the same model.
– Retrieve the top-k most similar chunks (k=3 to 5 is typical for Q&A).
– Optionally rerank results with a cross-encoder (e.g., `BAAI/bge-reranker-v2-m3`) for higher precision.
Generation
– Pass the retrieved chunks as context into the prompt of an LLM (e.g., Llama 3, Mistral, or a cloud API).
– Instruct the model to answer only from the provided context, with a citation when possible.
Trade-offs and Failure Modes
- Chunk size vs. relevance: Smaller chunks improve retrieval precision but may miss context. Large chunks increase recall but risk diluting the answer. Test with your corpus.
- Embedding model quality: A weak embedding model can miss relevant documents. Always benchmark on your own data.
- Vector store index – HNSW builds a graph that is fast but memory-intensive. FAISS IVF is more memory efficient but slower at high recall.
- Hallucination despite retrieval: If the retrieved chunks are irrelevant, the LLM may still generate plausible but wrong answers. Always add a “no relevant context” fallback instruction.
- Latency: The full pipeline (embedding + retrieval + generation) can take 3–10 seconds. Cache frequent queries or use a smaller LLM for shorter responses.
Sources and Caveats
This guide is based on official documentation from LangChain, LlamaIndex, Chroma, FAISS, and Qdrant as of March 2025. The choices and recommendations reflect common production patterns; your specific use case may require different configurations. The comparison table does not include proprietary vector databases like Pinecone or Weaviate Cloud, which offer managed infrastructure but are not open source. The failure modes listed are derived from community reports and official documentation; actual results depend on your data quality and pipeline tuning.
Next Steps
- Start with Chroma and a small document set to validate the pipeline.
- Measure retrieval recall and precision using a labeled test set.
- If using FAISS, implement a persistence layer (e.g., with SQLite) to avoid rebuilding the index on restart.
- Consider adding a reranking step once retrieval accuracy stabilizes.
- For highly dynamic data, adopt Qdrant with its incremental update support rather than a full re-index.
Lena Walsh
Colaborador editorial.
