Spaces:
Running
Cortex RAG β Architecture & Implementation Guide
This document provides a deep dive into the architecture of Cortex, a production-grade Retrieval-Augmented Generation (RAG) system. This guide is structured to help you explain the "what", "how", and "why" of each layer during your GenAI Engineer interview.
ποΈ 1. High-Level Architecture Overview
Cortex follows a modular, multi-layer RAG architecture designed for high precision, scalability, and reliability. It moves beyond "naive RAG" by implementing:
- Semantic Data Ingestion (instead of fixed-size chunking)
- Hybrid Multi-Strategy Retrieval (Dense + Sparse + Knowledge Graph)
- Corrective Gating (CRAG) (to handle retrieval failures)
- Reference-Free Evaluation (using RAGAS)
π₯ 2. Ingestion Layer: "Context-Aware Processing"
Document Loading
- Supports multiple formats: PDF, HTML, and TXT.
- Implementation:
DocumentLoaderhandles parsing and basic cleaning.
Semantic Chunker (ingestion/chunker.py)
- The Problem: Fixed-size chunking (e.g., 512 tokens) often splits mid-sentence or mid-concept, losing semantic coherence.
- The Solution: We use Sentence-Level Semantic Boundary Detection.
- How it works:
- Split text into individual sentences.
- Embed each sentence using
BAAI/bge-small-en-v1.5. - Compute the cosine similarity between consecutive sentence embeddings.
- Insert a chunk boundary whenever the similarity drops below a certain threshold (e.g., 0.82) or the token limit is reached.
- Why? This ensures each chunk contains a single, coherent topic.
Parent-Child Hierarchy
- The Problem: Small chunks are better for retrieval precision, but large chunks provide better context for generation.
- The Implementation:
- Child Chunks (~256 tokens): These are the units indexed in the vector database. They represent a specific "nugget" of information.
- Parent Chunks (~1024 tokens): A wider window of text centered on the child. When a child is retrieved, its parent text is what gets sent to the LLM.
- Why? It decouples retrieval granularity (find exactly what you need) from context width (give the LLM enough room to understand).
π 3. Retrieval Layer: "Multi-Strategy Orchestration"
Cortex doesn't just rely on vector search; it uses a MultiStrategyRetriever to combine different search paradigms.
A. Dense Retrieval (Milvus)
- Embeddings:
bge-small-en-v1.5(384-dim). - Vector DB: Milvus (Dockerized).
- Indexing:
IVF_FLATwithCOSINEsimilarity metric. - Why? Captures semantic meaning (e.g., "puppy" matches "dog").
B. Sparse Retrieval (BM25)
- Implementation:
rank_bm25library. - Why? Essential for exact keyword matching, acronyms, and specific names (e.g., "Project Cortex-X1") where vector search might be too "fuzzy".
C. Knowledge Graph (GraphRAG)
- Extraction: During ingestion, we use spaCy for Named Entity Recognition (NER) and REBEL (or LLM) for relation extraction.
- Storage: A NetworkX graph storing triples:
(Subject) --[Predicate]--> (Object). - Retrieval:
- Extract entities from the user query.
- Traverse the graph to find related nodes (multi-hop traversal).
- Retrieve the chunks associated with those nodes.
- Why? Solves "multi-hop" queries where the answer requires connecting disparate pieces of information across the document.
D. Fusion & Reranking (retrieval/fusion.py)
- RRF (Reciprocal Rank Fusion): Combines the ranked lists from Milvus, BM25, and the Graph into one unified list.
- Cross-Encoder Reranker: We take the top-15 fused candidates and run them through a Cross-Encoder (e.g.,
BAAI/bge-reranker-base). - Why? Cross-encoders are much more accurate (but slower) than vector search because they look at the query and chunk simultaneously. Using them as a final "filter" boosts precision significantly.
π§ 4. Generation Layer: "Corrective RAG (CRAG)"
The CRAGGate (generation/crag.py) acts as a "quality control" layer between retrieval and the LLM.
The CRAG Workflow
- Grading: An LLM-as-judge assesses if the retrieved chunks are relevant to the query.
- Action Categories:
- GOOD: Chunks are relevant. Proceed to generation.
- POOR: Chunks are partially relevant. Rewrite the query (using CoT) and re-retrieve to find better results.
- ABSENT: Knowledge base doesn't have the answer. Fallback to Web Search (Tavily/DuckDuckGo).
- LLM Generation: Uses Groq (Llama 3), OpenAI, or NVIDIA NIM to generate the final answer with inline citations (e.g., "The sky is blue [1].").
π 5. Evaluation Layer: "Reference-Free Metrics"
Since production RAG systems often lack "ground truth" answers, we use the RAGAS framework (evaluation/ragas_eval.py).
Key Metrics
- Faithfulness: Does the answer stay true to the retrieved context? (Prevents hallucinations).
- Answer Relevancy: Does the answer actually address the user's question?
- Context Precision: Were the retrieved chunks actually useful?
- Context Utilisation: What % of retrieved chunks were actually cited?
Implementation
- Evaluations run asynchronously in background threads so they don't slow down the user's response time.
- Results are stored in a local SQLite DB for monitoring.
π οΈ 6. System & Infrastructure
- API: FastAPI for high-performance, asynchronous endpoints.
- UI: Streamlit for a clean, interactive dashboard (Ask, Ingest, Monitor).
- Cache: Redis for caching query results (TTL-based) to save LLM costs and latency.
- Deployment: Full Docker Compose setup for Milvus, Redis, API, and UI.
π‘ Interview Tip: "Why this architecture?"
If asked why you built it this way, emphasize these three points:
- Precision: By using Semantic Chunking and Cross-Encoder Reranking, we ensure only the most relevant context reaches the LLM.
- Reliability: CRAG ensures the system doesn't hallucinate when the knowledge base is missing information.
- Observability: By integrating RAGAS, we have an automated way to track performance and catch regressions.
Good luck with your interview! π