1# RAG Pipeline — Production Implementation
2
3# ═══════════════════════ PHASE 1: INGEST ═══════════════════════
4
5docs = loader.load_directory("knowledge_base/")
6# → ['rag-guide.pdf', 'vector-db-101.txt', 'chunking.md']
7
8# ═══════════════════════ PHASE 2: CHUNK ════════════════════════
9
10splitter = RecursiveTextSplitter(
11 chunk_size=512,
12 chunk_overlap=50
13)
14chunks = splitter.split(docs)
15# → 847 chunks created from 3 documents
16
17# ═══════════════════════ PHASE 3: EMBED ════════════════════════
18
19embedder = OpenAIEmbeddings(model="text-embedding-3-small")
20embeddings = embedder.embed_batch(chunks)
21# → 847 vectors of dimension 1536
22
23# ═══════════════════════ PHASE 4: INDEX ════════════════════════
24
25vector_store = QdrantClient(url="localhost:6333")
26vector_store.upsert(
27 collection="knowledge",
28 vectors=embeddings
29)
30# → Stored 847 vectors
31
32# ═══════════════════════ PHASE 5: QUERY ════════════════════════
33
34query = "How does reranking improve retrieval precision?"
35query_vec = embedder.embed(query)
36# → Query vector: [0.12, -0.43, 0.87, ..., 0.21] (1536 dims)
37
38# ═══════════════════════ PHASE 6: RETRIEVE ═════════════════════
39
40raw_results = vector_store.search(
41 query_vec,
42 k=20, # over-fetch for reranker
43 score_threshold=0.65
44)
45# → 20 candidates from 847 vectors (23ms)
46
47# ═══════════════════════ PHASE 7: RERANK ═══════════════════════
48
49reranker = CrossEncoderReranker(model="ms-marco-MiniLM-L-6-v2")
50top_k = reranker.rerank(query, raw_results, top_k=5)
51# → Precision improved: 0.71 → 0.89
52
53# ═══════════════════════ PHASE 8: GENERATE ═════════════════════
54
55context = format_context(top_k)
56response = llm.chat([
57 {"role": "system", "content": SYSTEM_PROMPT},
58 {"role": "user", "content": f"{context}\n\nQuestion: {query}"}
59])
60# → Grounded answer with citations from knowledge base
61