DEV Community

niuniu
niuniu

Posted on

Quick Tip: Build a RAG Pipeline in 10 Lines of Python (No LangChain Needed)

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."
Enter fullscreen mode Exit fullscreen mode

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))
Enter fullscreen mode Exit fullscreen mode

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

  1. Chunk your documents — Don't embed entire pages. Split into 500-token chunks.
  2. Use metadata — Store source URLs alongside embeddings.
  3. 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
Enter fullscreen mode Exit fullscreen mode

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)