LocalGPT

repository·main·Indexed 12 days ago

https://github.com/promtengineer/localgpt

A private, on-premise Document Intelligence platform using Retrieval-Augmented Generation (RAG) to securely chat with local files. It features a hybrid search engine, smart routing, and a multimodal RAG system that processes both text and images from PDFs using LanceDB, Ollama, and models such as llama3 and qwen2.5vl:7b.

Tokens
43.2K
Snippets
105
Records
172
Agent score
95%

What's inside LocalGPT

  1. Overview of the LocalGPT Indexing Pipeline

    main

    The Indexing Pipeline transforms raw documents (such as PDF or TXT files) into search-ready chunks. The process involves converting files to text, chunking the text using various strategies, optionally enriching chunks with contextual summaries, generating embeddings, and finally storing the vectors in LanceDB. It also generates auxiliary assets like overviews in JSONL format for triage routing.

    flowchart TD
        A["Uploaded Files"] --> B{Converter}
        B -->|PDF→text| C["Plain Text"]
        C --> D{Chunker}
        D -->|docling| D1[DocLing Chunking]
        D -->|latechunk| D2[Late Chunking]
        D -->|standard| D3[Fixed-size]
        D1 & D2 & D3 --> E["Contextual Enricher"]
        E -->|local ctx summary| F["Embedding Generator"]
        F -->|vectors| G[(LanceDB Table)]
        E --> H["Overview Builder"]
        H -->|JSONL| OVR[[`index_store/overviews/<idx>.jsonl`]]
  2. What is LocalGPT?

    main

    LocalGPT is a private, on-premise Document Intelligence platform designed for secure RAG (Retrieval-Augmented Generation). It allows users to query, summarize, and extract insights from local files without data leaving the machine.

    Key architectural features include:

    • Hybrid Search Engine: Combines semantic similarity, keyword matching, and Late Chunking for high precision.
    • Smart Router: Automatically decides whether to use RAG or direct LLM answering for a query.
    • Contextual Enrichment & Pruning: Uses AI-generated context and sentence-level pruning to surface only relevant content.
    • Modular Design: A pure-Python core with minimal dependencies that allows enabling only necessary components.
  3. Understand the LocalGPT Docker Architecture

    main

    LocalGPT uses a multi-container architecture where the frontend, backend, and RAG API communicate via specific ports, while the heavy AI lifting is offloaded to a local Ollama instance on the host.

    Component Breakdown

    • Frontend (rag-frontend): Next.js web interface. Port: 3000.
    • Backend (rag-backend): Handles session management, chat history, and acts as an API gateway. Port: 8000.
    • RAG API (rag-api): Handles document indexing, retrieval, and AI processing. Port: 8001.
    • Ollama (Host): Local AI engine. Port: 11434.

    Data Persistence

    The following directories are mounted as volumes to ensure data persists across container restarts:

    • ./lancedb/: Vector database storage.
    • ./index_store/: Document indexes and metadata.
    • ./shared_uploads/: Uploaded document files.
    • ./backend/chat_data.db: SQLite chat history database.
  4. Use Late-Chunk Merging for improved context

    main

    To solve the problem of small chunks losing context or large chunks diluting relevance, the pipeline uses a Late-Chunk Merging algorithm. It retrieves specific small chunks and then expands the context by fetching neighboring chunks from LanceDB.

    By default, the system expands with a window_size of 5 chunks (approximately 2500 tokens) to provide richer context for answer generation while maintaining granular search precision.

  5. The Document Processing and Retrieval Pipeline

    main

    Indexing Process

    1. Upload: PDF files are uploaded via the web interface.
    2. Extraction: The Docling library extracts text while preserving layout.
    3. Chunking: Text is split using strategies like DocLing, Late Chunking, or Standard.
    4. Embedding: Text is converted to vectors using Qwen models.
    5. Storage: Vectors go to LanceDB and metadata goes to SQLite.

    Retrieval Process

    1. Query Processing: The user query is analyzed and contextualized.
    2. Embedding: The query is converted to a vector.
    3. Search: A hybrid search is performed, combining vector similarity and BM25 keyword matching.
    4. Reranking: An AI-powered reranker optimizes results for relevance.
    5. Synthesis: The LLM generates a final answer using the retrieved context.
  6. Understand the Indexing Pipeline architecture

    main

    The IndexingPipeline follows a sequential processing pattern designed for efficient memory usage and progress tracking. It processes documents through several distinct stages in order. If a stage is optional (like contextual enrichment or graph extraction), it is skipped if the corresponding component is not provided.

    The pipeline stages are:

    1. Document Processing & Chunking: Converting files to text and splitting them into manageable pieces.
    2. Contextual Enrichment (optional): Using an LLM to add context to chunks.
    3. Dense Indexing: Generating embeddings and storing them in a vector database.
    4. Graph Extraction (optional): Extracting relationships for graph-based retrieval.
    def run(self, file_paths: List[str]):
        with timer("Complete Indexing Pipeline"):
            # Stage 1: Document Processing & Chunking
            all_chunks = []
            doc_chunks_map = {}
            
            # Stage 2: Contextual Enrichment (optional)
            if self.contextual_enricher:
                all_chunks = self.contextual_enricher.enrich_batch(all_chunks)
            
            # Stage 3: Dense Indexing (embedding + storage)
            if self.vector_indexer:
                self.vector_indexer.index_chunks(all_chunks, table_name)
            
            # Stage 4: Graph Extraction (optional)
            if self.graph_extractor:
                self.graph_extractor.extract_and_store(all_chunks)
  7. Understand the Multimodal RAG Architecture and Data Flow

    main

    The system is organized into several functional modules that orchestrate the flow from raw PDF to a human-readable answer.

    Key Modules

    • main.py: The entry point that configures models and orchestrates pipelines.
    • rag_system/pipelines/: High-level orchestration.
      • indexing_pipeline.py: Converts raw PDFs into searchable data.
      • retrieval_pipeline.py: Handles query processing, retrieval, and answer generation.
    • rag_system/indexing/: Data processing and storage.
      • multimodal.py: Extracts text/images and generates embeddings (using colqwen2-v1.0).
      • representations.py: Defines text embedding models (e.g., Qwen2-7B-instruct).
      • embedders.py: Manages LanceDB vector database connections.
    • rag_system/retrieval/: Search and ranking.
      • retrievers.py: Searches LanceDB for text and image chunks.
      • reranker.py: Contains QwenReranker for relevance ordering.
    • rag_system/agent/: The user interaction loop.
    • rag_system/utils/: Utility clients like OllamaClient.

    Data Flow

    1. Indexing: MultimodalProcessor splits PDFs $\rightarrow$ extracts text and page images $\rightarrow$ QwenEmbedder (text) and LocalVisionModel (image) generate embeddings $\rightarrow$ VectorIndexer stores them in LanceDB tables.
    2. Retrieval: User query $\rightarrow$ MultiVectorRetriever searches LanceDB $\rightarrow$ QwenReranker re-orders results $\rightarrow$ Top results (text + images) passed to VLM (qwen-vl) $\rightarrow$ VLM extracts facts $\rightarrow$ llama3 synthesizes the final answer.
  8. Implement Contextual Enrichment with LLMs

    main

    The ContextualEnricher improves retrieval quality by generating summaries for text chunks using an LLM. This is performed in batches using a ThreadPoolExecutor to manage memory and speed.

    Enrichment Process:

    1. Chunks are processed in batches defined by batch_size.
    2. For each chunk, a prompt is sent to the LLM (e.g., qwen3:0.6b) asking for a concise summary of the main topics, context within the document, and relevance for search.
    3. The resulting summary is appended to the chunk's metadata.
    class ContextualEnricher:
        def enrich_batch(self, chunks: List[Dict]) -> List[Dict]:
            # ... processes chunks in batches using ThreadPoolExecutor
  9. Understand the Retrieval Pipeline architecture

    main

    The Retrieval Pipeline is responsible for taking a user query and indexed tables to retrieve relevant text chunks and synthesize an answer. It follows a multi-stage flow:

    1. Query Pre-processing: Uses a QueryTransformer (e.g., HyDEGenerator, GraphQueryTranslator) to expand or rewrite the raw query.
    2. Retrieval: Executes search via BM25Retriever, DenseRetriever, or a HybridRetriever against LanceDB vector and Full-Text Search (FTS) indices.
    3. Reranking: Optionally uses a reranker (like ColBERTSmall) to re-order results based on relevance.
    4. Synthesis: An LLM (via Ollama) uses the top-K chunks to generate and stream a final answer with sources.

    The pipeline is exposed via the RetrievalPipeline.answer_stream() iterator, which is designed to be consumed by an SSE (Server-Sent Events) API.

    flowchart LR
        Q["User Query"] --> XT["Query Transformer"]
        XT -->|variants| RETRIEVE
        subgraph Retrieval
            RET_BM25[BM25] --> MERGE
            RET_DENSE[Dense Vector] --> MERGE
            style RET_BM25 fill:#444,stroke:#ccc,color:#fff
            style RET_DENSE fill:#444,stroke:#ccc,color:#fff
        end
        MERGE --> RERANK
        RERANK --> K[["Top-K Chunks"]
        K --> SYNTH["Answer Synthesiser\n(LLM)"]
        SYNTH --> A["Answer + Sources"]
  10. Understand the LocalGPT System Architecture

    main

    LocalGPT follows a client-server architecture designed for private document intelligence. The system is composed of a Next.js frontend, a Python backend, and a core rag_system package that manages the RAG (Retrieval-Augmented Generation) lifecycle.

    High-Level Data Flow

    1. Frontend Interaction: Users interact with the Next.js UI. API requests are dispatched via src/lib/api.ts using HTTP/JSON.
    2. Backend Processing: backend/server.py receives requests, handles CORS, and proxies them to the rag_system core.
    3. Agent Decision (Triage): The Agent Loop (rag_system/agent/loop.py) uses a Triage system to decide between performing RAG or providing a direct LLM answer.
    4. RAG Execution: If RAG is triggered, the Retrieval Pipeline (pipelines/retrieval_pipeline.py) fetches candidates from LanceDB (using BM25 and dense vectors), an AI Reranker (HuggingFace) sorts them, and the Answer Synthesiser uses Ollama to generate the response.
    5. Verification: An optional Verifier performs grounding checks on the generated answers.
    6. Indexing: An offline pipeline chunks and embeds uploaded files (e.g., PDFs) into LanceDB.

    Storage and Model Providers

    • LanceDB: Stores vector tables (chunks and embeddings).
    • SQLite: Manages chat history and metadata.
    • Ollama: Hosts local LLMs (e.g., qwen3).
    • HuggingFace: Provides hosted embedding and reranker models.
  11. How the Multimodal RAG System works

    main

    The Multimodal RAG (Retrieval-Augmented Generation) system is a pipeline designed to process PDF documents by extracting both text and visual data (images). Unlike text-only RAG, this system allows a Vision Language Model (VLM) to reason over both modalities to answer complex queries.

    Core Capabilities

    • Multimodal Indexing: Extracts and creates separate vector embeddings for text and images from PDFs.
    • Hybrid Retrieval: Combines dense vector search (semantic similarity) with keyword-based search (BM25).
    • Advanced Reranking: Uses a reranker model to refine the relevance of retrieved chunks.
    • VLM-Powered Synthesis: Uses a VLM to analyze retrieved text and images before a final text generation model synthesizes the answer.
  12. How the LocalGPT RAG system works

    main

    The LocalGPT RAG (Retrieval-Augmented Generation) system is a multimodal question-answering system that processes both text and visual layouts. It uses an agentic workflow to decompose complex questions, triage queries, and verify answers against retrieved context.

    The system operates through two primary pipelines:

    1. Indexing Pipeline: Converts documents into a searchable knowledge base. It extracts text using PyMuPDF, generates embeddings using Qwen/Qwen3-Embedding-0.6B, extracts entities/relationships via a GraphExtractor (using qwen2.5vl:7b) to build a .gml knowledge graph, and stores everything in a LanceDB database.
    2. Retrieval Pipeline: Answers queries using an agentic flow. It performs Triage (deciding if retrieval is needed), Query Decomposition (breaking down complex queries via QueryDecomposer), Retrieval (using MultiVectorRetriever and GraphRetriever), Verification (checking context sufficiency via a Verifier), and Synthesis (generating the final answer).