L
Artificial Intelligence & LLM • Literally Web ID

Membangun Sistem RAG (Retrieval-Augmented Generation) Skala Enterprise dengan LLM dan Vector Database

⏱️ 18 menit baca • 📅 14 Oct 2026 • 👁️ 1 views
Membangun Sistem RAG (Retrieval-Augmented Generation) Skala Enterprise dengan LLM dan Vector Database

1. Konteks Industri & Analisis Akar Masalah

Dalam lanskap enterprise modern, pengetahuan tersebar di berbagai silo: dokumentasi internal di Confluence, file spesifikasi teknis di S3/MinIO, repositori kode di GitLab, dan wiki departemental. Model Bahasa Besar (LLM) seperti Llama 3 atau Mistral yang berjalan secara lokal menawarkan kemampuan penalaran luar biasa, namun memiliki dua keterbatasan mendasar: knowledge cutoff (ketidaktahuan terhadap data setelah pelatihan model) dan halusinasi fatal saat ditanya mengenai informasi spesifik perusahaan.

Pendekatan Retrieval-Augmented Generation (RAG) hadir sebagai jembatan yang menghubungkan LLM dengan gudang data korporat secara real-time. Namun, membangun sistem RAG skala enterprise jauh melampaui sekadar skrip Python dasar yang memanggil API OpenAI dan mencarinya di ChromaDB lokal.

Bottleneck Performa & Keamanan di Dunia Nyata

  • Latensi Pencarian Vektor: Kueri semantik pada jutaan dokumen tanpa indeks IVF (Inverted File Index) atau HNSW (Hierarchical Navigable Small World) yang teroptimasi akan menghabiskan resource CPU dan memperlambat respons hingga ribuan milidetik.
  • Kualitas Kontekstual & Chunking Semantik: Pemecahan teks dokumen yang naif (misalnya, berdasarkan jumlah karakter tetap) sering kali memutus kalimat di tengah, menghilangkan konteks penting dan mengakibatkan hallucination pada LLM.
  • Isolasi Data & Keamanan Multi-Tenancy: Dokumen HR atau keuangan tidak boleh bocor ke query karyawan departemen pemasaran. Sistem RAG enterprise wajib memiliki filter metadata berbasis peran (role-based access control - RBAC) langsung di tingkat vector database.
  • Infrastruktur Web & API Bottleneck: Tanpa reverse proxy Nginx yang dikonfigurasi dengan keep-alive, manajemen koneksi Redis untuk caching, serta pembatasan rate-limiting, backend API RAG akan rentan terhadap serangan DDoS atau kehabisan memori (OOM Killer) saat terjadi lonjakan traffic internal.

Kondisi Sebelum vs Sesudah Penerapan

  • Sebelum RAG Enterprise: Tim support dan engineer menghabiskan waktu rata-rata 45 menit per hari mencari informasi di berbagai sistem silo. Jawaban dari LLM publik tidak akurat dan berisiko membocorkan data rahasia perusahaan ke penyedia AI eksternal.
  • Sesudah RAG Enterprise: Sistem pencarian dokumen terintegrasi secara internal dengan latensi sub-detik (<300ms). LLM lokal memproses dokumen sensitif di dalam private cloud perusahaan, menjamin kepatuhan regulasi GDPR/SOC2, dan memberikan jawaban akurat bersumber dari dokumen internal yang valid.

2. Konsep Inti & Deep Dive Arsitektur

Arsitektur RAG enterprise menggabungkan lapisan web modern, antrian asinkron, mesin embedding, vector database berperforma tinggi (seperti Milvus atau Qdrant), dan inferensi LLM lokal yang diorkestrasi dengan baik.

+-----------------------------------------------------------------------------------+
|                                INGRESS & SECURITY                                 | 
|  [Client Web/App] ---> [Cloudflare CDN/WAF] ---> [Nginx Reverse Proxy & SSL]     | 
+-----------------------------------------------------------------------------------+
                                          |
                                          v
+-----------------------------------------------------------------------------------+
|                              BACKEND & PIPELINE API                               |
|             [Go / Node.js API Service - Fiber / Express]                          | 
+-----------------------------------------------------------------------------------+
              |                                                     |
              v (Async Ingestion)                                   v (Real-time Query)
+-------------------------------+                   +-------------------------------+
|    STORAGE & WORKER PIPELINE  |                   |        VECTOR SEARCH          |
|  [S3/MinIO Document Storage]  |                   |   [Milvus / Qdrant Database]  |
|  [Redis Queue + Supervisor]   |                   +-------------------------------+
+-------------------------------+                                   |
              |                                                     |
              +----------------------------------+------------------+
                                                 |
                                                 v
                                    +-------------------------------+
                                    |      LLM LOCAL INFERENCE      | 
                                    |   [Ollama / vLLM (Mistral)]   |
                                    +-------------------------------+

Alur Data di Bawah Hood (Under the Hood)

  1. Ingestion Pipeline (Offline/Batch):
    • Dokumen diunggah ke S3/MinIO.
    • Webhook memicu antrean backend (Go/Node.js) via Redis Queue yang dikelola Supervisor.
    • Dokumen diurai (parsing PDF/Markdown), melalui proses Semantic Chunking, lalu diubah menjadi vektor numerik oleh Embedding Model (e.g., BGE-large-en atau text-embedding-3).
    • Vektor beserta metadata (department, access_level, timestamp) disimpan ke Milvus/Qdrant.
  2. Retrieval & Generation Pipeline (Online/Real-time):
    • Klien mengirimkan pertanyaan (query) melalui REST/WebSocket ke Nginx.
    • Backend mengonversi query menjadi vektor embedding.
    • Vector database melakukan pencarian jarak kosinus (Cosine Similarity) atau Inner Product dengan filter metadata RBAC.
    • Konteks teratas (top-k chunks) digabungkan dengan prompt asli dan dikirim ke mesin LLM lokal (vLLM/Ollama).
    • Hasil jawaban dikembalikan ke klien secara streaming via Server-Sent Events (SSE) atau WebSocket.

3. Perbandingan Komparatif / Analisis Pendekatan

Komponen / Fitur Pendekatan Naif (Basic Python Script) Pendekatan Enterprise Skala Produksi
Vector DB ChromaDB / FAISS (In-Memory Lokal) Milvus / Qdrant (Distributed, HNSW Index)
Backend Integration Flask/FastAPI single instance Go / Node.js Microservice + Nginx + Redis Cache
Chunking Strategy Fixed-size character splitting Semantic Chunking berbasis struktur dokumen
Keamanan & Auth Tanpa kontrol akses dokumen RBAC berbasis metadata per kueri di Vector DB
Skalabilitas Bottleneck pada RAM & Single Thread Horizontal Scaling dengan Kubernetes / Docker Swarm
Latensi Rata-rata 2000ms - 5000ms < 350ms (dengan Redis Caching & Indexing)

4. Prasyarat Sistem & Persiapan Lingkungan

Untuk menjalankan arsitektur RAG enterprise pada server produksi (Ubuntu 22.04 LTS / Debian 12), pastikan spesifikasi minimal terpenuhi:

  • CPU: 8 Cores / 16 Threads
  • RAM: 32 GB (Disarankan 64 GB untuk menjalankan LLM ukuran 7B/13B secara lokal)
  • Storage: NVMe SSD 500GB
  • GPU: NVIDIA GPU dengan VRAM minimal 16GB (RTX 4090 atau A10G) untuk akselerasi vLLM/Ollama.

Instalasi Dependensi Dasar di Server:

sudo apt update && sudo apt upgrade -y
sudo apt install -y curl git build-essential nginx ufw fail2ban redis-server
sudo systemctl enable --now redis-server

5. Panduan Implementasi Langkah demi Langkah

Langkah 1: Konfigurasi Docker Compose untuk Qdrant dan Ollama

Buat file /opt/rag-stack/docker-compose.yml:

version: '3.8'

services:
  qdrant:
    image: qdrant/qdrant:v1.9.0
    container_name: qdrant_enterprise
    restart: always
    ports:
      - "6333:6333"
      - "6334:6334"
    volumes:
      - /opt/rag-stack/qdrant_storage:/qdrant/storage
    environment:
      - QDRANT__SERVICE__HTTP_PORT=6333

  ollama:
    image: ollama/ollama:latest
    container_name: ollama_inference
    restart: always
    ports:
      - "11434:11434"
    volumes:
      - /opt/rag-stack/ollama_data:/root/.ollama
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]

Jalankan layanan stack:

cd /opt/rag-stack
docker compose up -d

Langkah 2: Skrip Backend Node.js (TypeScript) untuk Pencarian RAG

Inisialisasi project backend di /opt/rag-stack/backend:

{
  "name": "enterprise-rag-backend",
  "version": "1.0.0",
  "main": "dist/index.js",
  "scripts": {
    "build": "tsc",
    "start": "node dist/index.js"
  },
  "dependencies": {
    "@qdrant/js-client-rest": "^1.9.0",
    "axios": "^1.6.8",
    "express": "^4.19.2",
    "redis": "^4.6.13"
  },
  "devDependencies": {
    "@types/express": "^4.17.21",
    "typescript": "^5.4.5"
  }
}

Buat file kode utama /opt/rag-stack/backend/src/index.ts:

import express, { Request, Response } from 'express';
import { QdrantClient } from '@qdrant/js-client-rest';
import { createClient } from 'redis';
import axios from 'axios';

const app = express();
app.use(express.json());

const qdrant = new QdrantClient({ host: 'localhost', port: 6333 });
const redisClient = createClient({ url: 'redis://localhost:6379' });

redisClient.on('error', (err) => console.error('Redis Client Error', err));

const COLLECTION_NAME = 'enterprise_docs';

async function getEmbedding(text: string): Promise<number[]>
{
  try {
    const response = await axios.post('http://localhost:11434/api/embeddings', {
      model: 'bge-large',
      prompt: text
    });
    return response.data.embedding;
  } catch (error) {
    console.error('Error generating embedding:', error);
    throw error;
  }
}

app.post('/api/v1/rag/query', async (req: Request, res: Response) => {
  const { query, department } = req.body;
  if (!query) {
    return res.status(400).json({ error: 'Query is required' });
  }

  try {
    // Cek cache Redis terlebih dahulu untuk mengurangi latensi
    const cacheKey = `rag:${department}:${query}`;
    const cachedResult = await redisClient.get(cacheKey);
    if (cachedResult) {
      return res.json({ source: 'cache', response: JSON.parse(cachedResult) });
    }

    // 1. Generate Query Embedding
    const queryVector = await getEmbedding(query);

    // 2. Vector Search dengan Filter Metadata RBAC
    const searchResult = await qdrant.search(COLLECTION_NAME, {
      vector: queryVector,
      limit: 3,
      filter: {
        must: [
          { key: 'department', match: { value: department } }
        ]
      }
    });

    const context = searchResult.map(item => item.payload?.text).join('\n\n');

    // 3. Susun Prompt untuk LLM Lokal
    const prompt = `Gunakan konteks berikut untuk menjawab pertanyaan secara akurat. Jika tidak tahu, katakan tidak tahu.\n\nKonteks:\n${context}\n\nPertanyaan: ${query}\nJawaban:`;

    // 4. Panggil LLM (Ollama)
    const llmResponse = await axios.post('http://localhost:11434/api/generate', {
      model: 'mistral',
      prompt: prompt,
      stream: false
    });

    const finalAnswer = llmResponse.data.response;

    // Simpan ke Redis cache selama 1 jam
    await redisClient.setEx(cacheKey, 3600, JSON.stringify(finalAnswer));

    res.json({ source: 'vector_db_and_llm', response: finalAnswer });
  } catch (error: any) {
    console.error(error);
    res.status(500).json({ error: 'Internal Server Error', details: error.message });
  }
});

async function startServer() {
  await redisClient.connect();
  app.listen(3000, () => {
    console.log('Enterprise RAG Backend running on port 3000');
  });
}

startServer();

Langkah 3: Konfigurasi Nginx sebagai Reverse Proxy

Buat file konfigurasi /etc/nginx/sites-available/rag-enterprise:

upstream rag_backend {
    server 127.0.0.1:3000;
    keepalive 32;
}

server {
    listen 80;
    server_name rag.internal.enterprise.com;

    # Redirect HTTP ke HTTPS menggunakan Let's Encrypt SSL
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name rag.internal.enterprise.com;

    ssl_certificate /etc/letsencrypt/live/rag.internal.enterprise.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/rag.internal.enterprise.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    client_max_body_size 50M;

    location / {
        proxy_pass http://rag_backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
}

Aktifkan konfigurasi Nginx:

sudo ln -s /etc/nginx/sites-available/rag-enterprise /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

6. Bedah Kode & Penjelasan Detail Baris Kunci

  • Metadata Filtering pada Qdrant (filter: { must: [...] }): Baris ini krusial untuk keamanan enterprise. Tanpa filter ini, pengguna dari divisi finansial dapat mengakses dokumen rahasia HR. Filter memastikan hanya potongan dokumen dengan atribut departemen yang sesuai yang dikembalikan.
  • Redis Caching (redisClient.get & redisClient.setEx): Pemanggilan LLM dan embedding memakan waktu komputasi yang tinggi. Dengan caching berbasis query dan department key, kueri berulang diselesaikan dalam waktu < 5ms tanpa membebani GPU.
  • Nginx proxy_http_version 1.1 & proxy_set_header Connection "": Pengaturan ini mengaktifkan HTTP Keep-Alive antara Nginx dan backend Node.js, mengurangi overhead pembuatan koneksi TCP baru secara signifikan pada traffic tinggi.

7. Skenario Produksi & Studi Kasus Dunia Nyata

[!TIP] Gunakan cluster Redis terpisah atau Redis Sentinel di lingkungan produksi berskala besar untuk menghindari single point of failure pada lapisan caching dan manajemen sesi antrean.

Pada perusahaan finansial dengan 10.000 karyawan aktif, lonjakan kueri terjadi setiap pagi jam 09.00 saat staf operasional menanyakan SOP terbaru. Dengan menerapkan penyeimbang beban Nginx di depan tiga replika backend Node.js, serta menggunakan indeks HNSW di Qdrant, sistem mampu menangani hingga 450 Requests Per Second (RPS) dengan latensi rata-rata di bawah 280ms.


8. Common Pitfalls, Anti-Patterns & Solusi

  • Anti-Pattern 1: Menggunakan in-memory database lokal (ChromaDB file-based) untuk produksi. Dampak: Menyebabkan korupsi data saat terjadi konkurensi tinggi dan memory leak pada proses Node.js/Python. Solusi: Gunakan database klien-server terdedikasi seperti Qdrant atau Milvus.
  • Anti-Pattern 2: Mengabaikan sanitasi teks pada dokumen masuk. Dampak: Injeksi prompt berbahaya (Prompt Injection) melalui dokumen yang diunggah pengguna eksternal. Solusi: Terapkan sanitasi input dan validasi parser dokumen ketat sebelum dikonversi menjadi embedding.

9. Benchmark, Metrik Kinerja & Tuning Performa

Lakukan pengujian beban menggunakan tool k6 untuk mengukur throughput API RAG:

import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  stages: [
    { duration: '1m', target: 50 },
    { duration: '3m', target: 200 },
    { duration: '1m', target: 0 },
  ],
};

export default function () {
  const url = 'https://rag.internal.enterprise.com/api/v1/rag/query';
  const payload = JSON.stringify({
    query: 'Bagaimana prosedur klaim asuransi kesehatan karyawan?',
    department: 'HR'
  });

  const params = {
    headers: { 'Content-Type': 'application/json' },
  };

  const res = http.post(url, payload, params);
  check(res, {
    'status is 200': (r) => r.status === 200,
    'response time < 500ms': (r) => r.timings.duration < 500,
  });
  sleep(1);
}

Tuning parameter lanjutan yang disarankan:

  • Optimalkan konfigurasi HNSW di Qdrant (m: 16, ef_construct: 100) untuk menyeimbangkan kecepatan pencarian dan akurasi recall.
  • Konfigurasikan worker_processes auto; dan worker_connections 10240; pada file /etc/nginx/nginx.conf untuk menangani koneksi konkuren dalam jumlah masif.

10. Checklist Penerapan Produksi & Kesimpulan

  • Konfigurasi SSL/TLS yang valid dengan Let's Encrypt dan pembaruan otomatis via Cron.
  • Implementasi Firewall (UFW) hanya membuka port 80, 443, dan membatasi akses SSH.
  • Pengaturan aturan Fail2ban untuk mencegah serangan brute-force pada endpoint API.
  • Pengujian backup berkala untuk data penyimpanan Qdrant dan MinIO.
  • Validasi isolasi metadata RBAC pada setiap kueri vector database.

Membangun sistem RAG skala enterprise menuntut perpaduan disiplin ilmu antara arsitektur web, manajemen infrastruktur server, dan rekayasa kecerdasan buatan. Dengan fondasi yang kokoh menggunakan Nginx, Redis, Qdrant, dan LLM lokal, perusahaan Anda dapat menikmati efisiensi pencarian informasi tingkat lanjut tanpa mengorbankan keamanan data dan kepatuhan privasi.

🏷️ Tags: #Nginx #Node.js #Rag #Vector Database #Ai