L
Artificial Intelligence & LLM • Literally Web ID

Membangun Sistem Retrieval-Augmented Generation (RAG) Menggunakan LLM Lokal dan Qdrant Vector Database

⏱️ 15 menit baca • 📅 14 Oct 2026 • 👁️ 1 views
Membangun Sistem Retrieval-Augmented Generation (RAG) Menggunakan LLM Lokal dan Qdrant Vector Database

1. Konteks Industri & Analisis Akar Masalah

Dalam lanskap enterprise modern, kecerdasan buatan generatif (GenAI) dan Large Language Models (LLM) telah bergeser dari sekadar eksperimen main-main menjadi tulang punggung operasional bisnis. Namun, adopsi LLM komersial seperti OpenAI GPT-4 atau Anthropic Claude menghadapi tembok besar yang tidak bisa ditawar: privasi data, latensi jaringan publik, dan biaya operasional per token yang membengkak secara eksponensial.

Perusahaan keuangan, layanan kesehatan, dan infrastruktur kritis tidak dapat mentransmisikan dokumen internal mereka—yang berisi kekayaan intelektual, catatan medis pasien, atau transaksi finansial—ke server pihak ketiga. Di sinilah arsitektur Retrieval-Augmented Generation (RAG) lokal lahir sebagai penyelamat mutlak. RAG menggabungkan presisi pencarian vektor (vector search) dengan kemampuan penalaran generatif LLM, semuanya berjalan di atas infrastruktur mandiri tanpa kabel data yang keluar dari perimeter jaringan internal perusahaan.

Namun, membangun sistem RAG lokal di dunia nyata bukan sekadar menjalankan skrip Python sederhana dari notebook Jupyter. Bottleneck performa sering kali menghantam pada tiga titik krusial:

  1. Inersia Ingesti Dokumen: Proses chunking yang buruk memecah konteks semantik, menyebabkan LLM gagal memahami relasi antar-paragraf.
  2. Keterbatasan Memori Vector Database: Qdrant atau milvus yang salah konfigurasi pada sistem berkas berbasis HDD alih-alih NVMe akan mengalami I/O bottleneck saat melakukan cosine similarity search skala besar.
  3. Latensi Inference Model Lokal: Menjalankan model seperti Llama 3 atau Mistral secara lokal membutuhkan orkestrasi resource GPU yang presisi melalui engine seperti Ollama atau vLLM.

Perbandingan Kondisi: Sebelum vs Sesudah Implementasi RAG Lokal

Metrik / Parameter Sebelum RAG Lokal (Cloud-based / Out-of-the-Box) Sesudah RAG Lokal Mandiri (Qdrant + LLM Lokal)
Keamanan & Privasi Data Risiko tinggi data leakage, data ditransmisikan ke API eksternal. 100% Air-gapped, data tidak pernah keluar dari server perusahaan.
Biaya Operasional (OPEX) Berbayar per token, membengkak drastis saat high concurrency. Fixed cost (biaya hardware/server), tanpa biaya tambahan per request.
Latensi Jaringan Bergantung pada stabilitas WAN/Internet publik (RTLT tinggi). Latensi rendah berbasis Local Area Network (LAN) atau Inter-process communication.
Kustomisasi & Kontrol Terikat pada batasan kebijakan penyedia layanan pihak ketiga. Kontrol penuh atas embedding model, chunk size, dan prompt engineering.

2. Konsep Inti & Deep Dive Arsitektur

Sistem RAG berbasis Qdrant dan LLM lokal beroperasi melalui dua fase utama yang terisolasi namun terintegrasi secara asinkron: Fase Ingesti Data (Offline Pipeline) dan Fase Query (Online Pipeline).

[Dokumen PDF/TXT] ---> [Parser & Chunking] ---> [Embedding Model (HuggingFace)]
                                                         |
                                                         v
                                                  [Qdrant Vector DB]
                                                         ^
[User Query] -------> [Query Embedding] --------------+|
                                                         |
                                                         v
                                               [Top-K Similarity Search]
                                                         |
                                                         v
[LLM Lokal (Ollama)] <--- [Context + Prompt] <----------+
         |
         v
[Final Response ke User]

Alur Kerja di Bawah Tenda (Under the Hood)

  1. Fase Ingesti (Data Preparation): Dokumen sumber mentah (PDF, Markdown, HTML) dibaca oleh parser. Teks dipecah menjadi potongan-potongan kecil (chunks) dengan ukuran optimal (misalnya 500 token) menggunakan teknik recursive character splitting untuk menjaga integritas struktur kalimat. Setiap chunk dikirim ke model embedding lokal (seperti bge-large-en-v1.5 atau all-minilm-l6-v2) untuk diterjemahkan menjadi vektor numerik berdimensi tinggi (misalnya 1024 dimensi).
  2. Penyimpanan di Qdrant: Vektor-vektor ini beserta metadata aslinya (nama file, nomor halaman, teks asli) disimpan ke dalam koleksi Qdrant. Qdrant menggunakan struktur indeks HNSW (Hierarchical Navigable Small World) yang dioptimalkan untuk pencarian tetangga terdekat (approximate nearest neighbor atau ANN) secara ultra-cepat.
  3. Fase Query (Runtime): Ketika pengguna mengirimkan pertanyaan melalui antarmuka web, pertanyaan tersebut diubah menjadi vektor menggunakan model embedding yang sama. Qdrant kemudian melakukan pemindaian vektor untuk menemukan $K$ dokumen paling relevan (Top-K retrieval).
  4. Augmentasi & Generasi: Teks dari dokumen hasil retrieval digabungkan ke dalam system prompt LLM sebagai konteks latar belakang (context injection). LLM lokal (yang berjalan di atas Ollama atau vLLM) membaca konteks tersebut dan menyusun jawaban yang akurat, terhindar dari halusinasi, dan menyertakan referensi sumber dokumen asli.

3. Perbandingan Komparatif / Analisis Pendekatan

Memilih komponen yang tepat untuk stack RAG lokal sangat menentukan performa jangka panjang. Berikut adalah analisis mendalam mengenai trade-off dari berbagai opsi komponen utama:

Komponen Opsi A: Qdrant + Ollama + LangChain Opsi B: Milvus + vLLM + LlamaIndex Opsi C: ChromaDB + Transformers Murni
Vector Database Qdrant (Rust-based, efisien RAM, HNSW indexing unggul) Milvus (Distributed, sangat cocok untuk skala miliaran vektor) ChromaDB (In-memory/SQLite, bagus untuk prototyping cepat)
LLM Inference Engine Ollama (Sangat mudah di-setup, mendukung manajemen model CLI) vLLM (Paging memory PagedAttention, throughput tinggi) HuggingFace Transformers (Fleksibel, namun berat untuk produksi)
Orchestration Framework LangChain (Ekosistem luas, integrasi melimpah) LlamaIndex (Spesialisasi tinggi untuk indeks data dokumen) Custom Python Script (Kontrol penuh, tanpa bloatware)
Konsumsi Resource (RAM/GPU) Menengah ke Atas (Stabil pada RAM 16GB+, VRAM 8GB+) Sangat Tinggi (Direkomendasikan untuk cluster enterprise) Rendah (Cocok untuk environment dengan resource terbatas)
Latensi Query Rata-rata 150ms - 400ms (Bergantung ukuran model & hardware) 100ms - 300ms (Dioptimalkan untuk skala besar) 300ms - 800ms (Menurun seiring bertambahnya ukuran koleksi)

[!WARNING] Jangan pernah menggunakan ChromaDB dengan default persistence SQLite untuk production environment dengan konkurensi tinggi karena risiko database locking. Gunakan Qdrant atau Milvus untuk arsitektur enterprise yang membutuhkan skalabilitas tinggi dan konkurensi I/O yang handal.


4. Prasyarat Sistem & Persiapan Lingkungan

Sebelum melangkah ke implementasi teknis, pastikan infrastruktur server atau mesin lokal Anda memenuhi spesifikasi minimum berikut agar sistem tidak mengalami OutOfMemory (OOM) crash saat melakukan embedding dokumen berukuran besar.

Spesifikasi Minimum Hardware

  • CPU: Minimal 8 Core (Disarankan Intel Xeon / AMD EPYC / Apple Silicon M-series).
  • RAM: Minimal 32 GB (Direkomendasikan 64 GB untuk menjalankan LLM berukuran 13B parameter secara bersamaan).
  • Storage: 100 GB NVMe SSD (Kecepatan I/O sangat kritikal untuk operasi Qdrant HNSW graph traversal).
  • GPU (Opsional tapi Sangat Disarankan): NVIDIA GPU dengan VRAM minimum 12 GB (misalnya RTX 3060/4060 atau RTX 3090/4090 untuk performa maksimal).

Software Dependencies

  • Ubuntu 22.04 LTS / Debian 12 / macOS Sonoma
  • Docker Engine (v24.0+) & Docker Compose (v2.20+)
  • Python 3.10 atau 3.11
  • CUDA Toolkit 12.1+ (Jika menggunakan akselerasi GPU NVIDIA)

Lakukan verifikasi awal pada sistem operasi Anda untuk memastikan Docker berjalan dengan benar:

# Verifikasi versi Docker dan Docker Compose
docker --version
docker compose version

# Verifikasi ketersediaan GPU NVIDIA (jika ada)
nvidia-smi

5. Panduan Implementasi Langkah demi Langkah

Langkah 1: Setup Qdrant Vector Database via Docker Compose

Buat direktori kerja baru di server Anda, lalu buat file docker-compose.yml untuk menjalankan Qdrant dan Ollama dalam satu stack jaringan internal.

version: '3.8'

services:
  qdrant:
    image: qdrant/qdrant:latest
    container_name: qdrant_vector_db
    restart: unless-stopped
    ports:
      - "6333:6333"
      - "6334:6334"
    volumes:
      - qdrant_data:/qdrant/storage
    environment:
      - QDRANT__SERVICE__HTTP_PORT=6333
      - QDRANT__SERVICE__GRPC_PORT=6334
    networks:
      - rag_net

  ollama:
    image: ollama/ollama:latest
    container_name: ollama_llm
    restart: unless-stopped
    ports:
      - "11434:11434"
    volumes:
      - ollama_data:/root/.ollama
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]
    networks:
      - rag_net

volumes:
  qdrant_data:
  ollama_data:

networks:
  rag_net:
    driver: bridge

Jalankan stack Docker di latar belakang:

docker compose up -d

Langkah 2: Download Model Lokal via Ollama

Masuk ke dalam container Ollama untuk mengunduh model LLM (llama3:8b) dan model embedding (bge-large atau gunakan HuggingFace embeddings melalui Python).

# Masuk ke container ollama
docker exec -it ollama_llm ollama run llama3:8b

# Setelah masuk, ketik /bye untuk keluar, atau unduh model tambahan
ollama pull mxbai-embed-large

Langkah 3: Setup Virtual Environment Python & Install Dependencies

python3 -m venv venv
source venv/bin/activate

pip install --upgrade pip
pip install langchain langchain-community langchain-qdrant qdrant-client sentence-transformers pypdf fastapi uvicorn

Langkah 4: Script Pipeline Ingesti Dokumen (ingest.py)

Buat file Python untuk memproses dokumen PDF dari direktori lokal, memecahnya menjadi chunks, membuat embeddings, dan menyimpannya ke Qdrant.

import os
from langchain_community.document_loaders import PyPDFDirectoryLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_qdrant import QdrantVectorStore
from qdrant_client import QdrantClient
from qdrant_client.http.models import Distance, VectorParams

# Konfigurasi koneksi
QDRANT_HOST = "localhost"
QDRANT_PORT = 6333
COLLECTION_NAME = "enterprise_docs"

# Direktori dokumen
DOCS_DIR = "./documents"

def ingest_documents():
    print("[+] Memulai proses ingesti dokumen...")
    
    # 1. Load dokumen PDF
    if not os.path.exists(DOCS_DIR):
        os.makedirs(DOCS_DIR)
        print(f"[!] Harap letakkan file PDF di dalam folder {DOCS_DIR}")
        return

    loader = PyPDFDirectoryLoader(DOCS_DIR)
    raw_documents = loader.load()
    print(f"[+] Berhasil memuat {len(raw_documents)} halaman dokumen.")

    # 2. Chunking dokumen
    text_splitter = RecursiveCharacterTextSplitter(
        chunk_size=1000,
        chunk_overlap=200,
        length_function=len,
    )
    docs = text_splitter.split_documents(raw_documents)
    print(f"[+] Dokumen dipecah menjadi {len(docs)} chunks.")

    # 3. Inisialisasi Model Embedding Lokal
    embeddings = HuggingFaceEmbeddings(
        model_name="BAAI/bge-large-en-v1.5",
        model_kwargs={"device": "cuda\
🏷️ Tags: #Nginx #High Concurrency #Performance #Sysadmin #Web Server