Everyone thinks you need LangChain or LlamaIndex to build a RAG pipeline. You don't.
Here's a working RAG system in 10 lines of Python using just openai and numpy.
The Code
import numpy as np
from openai import OpenAI
client = OpenAI()
def get_embedding(text):
resp = client.embeddings.create(model="text-embedding-3-small", input=text)
return np.array(resp.data[0].embedding)
def build_index(docs):
embeddings = [get_embedding(d) for d in docs]
return np.array(embeddings)
def search(query, index, docs, top_k=3):
q_emb = get_embedding(query)
scores = index @ q_emb / (np.linalg.norm(index, axis=1) * np.linalg.norm(q_emb))
top_idx = np.argsort(scores)[-top_k:][::-1]
return [(docs[i], scores[i]) for i in top_idx]
def ask(question, context):
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": f"Answer based on this context: {context}"},
{"role": "user", "content": question}
]
)
return resp.choices[0].message.content
# Usage
docs = [
"Python was created by Guido van Rossum in 1991.",
"Python is known for its readability and simplicity.",
"The Python Package Index (PyPI) has over 400,000 packages.",
"Python 3.12 introduced improved error messages.",
"Django and Flask are popular Python web frameworks."
]
index = build_index(docs)
results = search("Who created Python?", index, docs)
context = " ".join([r[0] for r in results])
answer = ask("Who created Python?", context)
print(answer)
# Output: "Python was created by Guido van Rossum in 1991."
Why This Works Better Than LangChain
| Feature | This (10 lines) | LangChain |
|---|---|---|
| Lines of code | 10 | 50+ |
| Dependencies | 2 | 15+ |
| Debuggable | ✅ Yes | ❌ Black box |
| Customizable | ✅ Full control | ⚠️ Abstractions |
| Learning curve | 5 minutes | 2 hours |
The Secret: Cosine Similarity
The magic is in one line:
scores = index @ q_emb / (np.linalg.norm(index, axis=1) * np.linalg.norm(q_emb))
This computes cosine similarity between your query and all documents. No vector database needed for < 10K documents.
When to Use What
- < 10K docs: This approach (numpy)
- 10K-1M docs: ChromaDB or Qdrant
- > 1M docs: Pinecone or Weaviate
Pro Tips
- Chunk your documents — Don't embed entire pages. Split into 500-token chunks.
- Use metadata — Store source URLs alongside embeddings.
- Hybrid search — Combine vector search with keyword search for better results.
# Better chunking
def chunk_text(text, chunk_size=500, overlap=50):
words = text.split()
chunks = []
for i in range(0, len(words), chunk_size - overlap):
chunks.append(" ".join(words[i:i + chunk_size]))
return chunks
Do you use LangChain/LlamaIndex, or do you prefer building RAG from scratch? I've found that understanding the fundamentals makes debugging 10x easier.
P.S. I'm building more Python AI tutorials at MonkeyCode — a free, open-source AI coding platform.
Top comments (0)