L
Artificial Intelligence & LLM • Literally Web ID

Deploying Local LLMs dengan Ollama dan Vector Database untuk Enterprise RAG

⏱️ 18 menit baca • 📅 15 Oct 2026 • 👁️ 1 views
Deploying Local LLMs dengan Ollama dan Vector Database untuk Enterprise RAG

Deploying Local LLMs dengan Ollama dan Vector Database untuk Enterprise RAG

1. Konteks Industri & Analisis Akar Masalah

Di era modern, perusahaan skala enterprise dihadapkan pada dilema krusial antara memanfaatkan kecerdasan buatan generatif (GenAI) atau menjaga kerahasiaan data internal yang sensitif. Ketergantungan pada Public API (seperti OpenAI, Anthropic, atau Google Gemini) sering kali membentur tembok regulasi ketat seperti GDPR, HIPAA, atau kebijakan internal tata kelola data perusahaan yang melarang pengiriman Personally Identifiable Information (PII) atau kekayaan intelektual ke infrastruktur pihak ketiga.

Bottle-neck utama dalam adopsi enterprise AI meliputi:

  • Kebocoran Data (Data Leakage): Risiko eksfiltrasi data saat melakukan API call eksternal.
  • Halusinasi Model (Hallucination): LLM umum tidak memiliki konteks spesifik domain bisnis, sehingga sering memberikan informasi fiktif namun meyakinkan.
  • Latency & Biaya Operasional: Pembayaran berbasis token (pay-per-token) membengkak seiring volume transaksi tinggi, ditambah latensi jaringan publik yang tidak stabil.
  • Vendor Lock-in: Keterikatan pada ekosistem satu penyedia layanan cloud.

Sebelum vs Sesudah Penerapan Enterprise Local RAG

  • Sebelum: Perusahaan menggunakan API pihak ketiga. Data dikirim ke cloud eksternal, latensi tinggi berkisar antara 800ms - 2500ms, biaya membengkak secara eksponensial berdasarkan jumlah prompt harian, dan rentan terhadap audit kepatuhan regulasi data.
  • Sesudah: Menggunakan Ollama lokal yang di-host di on-premise/private cloud, terintegrasi dengan Vector Database (Qdrant/Milvus) dan arsitektur backend Go/Node.js. Data 100% berada di bawah kendali internal, latensi turun drastis ke kisaran 150ms - 400ms untuk token pertama, zero cost per token, dan memenuhi standar keamanan enterprise tingkat tinggi.

2. Konsep Inti & Deep Dive Arsitektur

Sistem Retrieval-Augmented Generation (RAG) bekerja dengan menggabungkan kekuatan pencarian berbasis vektor (semantic search) dengan kemampuan generasi bahasa dari LLM.

Alur eksekusi data (data flow) pada arsitektur ini dapat dilihat pada diagram ASCII di bawah ini:

+------------------+       1. Raw Documents       +------------------------+
| Enterprise Docs  | ---------------------------> | Document Ingestion Svc |
| (PDF, DB, S3)    |                              | (Chunking & Embedding) |
+------------------+                              +------------------------+
                                                               |
                                                  2. Vector Embeddings
                                                               v
+------------------+       5. Final Response      +------------------------+
| User / Frontend  | <--------------------------- |   Vector Database      |
| (Web/Mobile App) |                              |   (Milvus / Qdrant)    |
+------------------+                              +------------------------+
   |              ^                                            ^
   | 3. Query     | 4. Contextual Prompt                       |
   +--------------+--------------------------------------------+
                                    |                          |
                                    v                          |
                         +--------------------------+          |
                         |      Ollama Engine       | --------+
                         |   (Local LLM Inference)  | Sem. Search
                         +--------------------------+

Penjelasan Alur Eksekusi:

  1. Document Ingestion Pipeline: Dokumen perusahaan diambil dari penyimpanan (S3/MinIO), dipecah menjadi beberapa bagian (chunking), lalu dikonversi menjadi representasi vektor numerik melalui model embedding.
  2. Vector Storage: Vektor disimpan ke dalam Vector Database (Qdrant/Milvus) untuk pencarian berbasis kemiripan kosinus (cosine similarity).
  3. User Query: Pengguna mengirimkan pertanyaan melalui frontend web.
  4. Context Retrieval: Backend melakukan embedding pada query pengguna dan mencari dokumen relevan di Vector Database.
  5. Generation: Query pengguna beserta konteks dokumen yang ditemukan digabungkan menjadi sebuah prompt yang diperkaya (augmented prompt), lalu dikirim ke Ollama untuk menghasilkan jawaban presisi.

3. Perbandingan Komparatif / Analisis Pendekatan

Berikut adalah tabel perbandingan komponen infrastruktur untuk menentukan pilihan terbaik sesuai skala enterprise:

Komponen Opsi A: Ollama + Qdrant + Go Backend Opsi B: Python LangChain + ChromaDB + vLLM Opsi C: Managed Cloud AI (OpenAI + Pinecone)
Bahasa Pemrograman Go (High Concurrency, Low Memory) Python (Rich AI Ecosystem) Fleksibel (Node.js / Python / PHP)
Penggunaan RAM/VRAM Efisien (Golang runtime + C++ Ollama) Sedang-Tinggi (Python Overhead) Minimal di server lokal (Offloaded)
Keamanan & Privasi 100% On-Premise / Air-Gapped 100% On-Premise / Air-Gapped Bergantung pada Cloud Provider
Latency / Performa Sangat Cepat (Native Binary) Cepat (Tergantung setup vLLM) Tergantung latensi jaringan internet
Skalabilitas Enterprise Tinggi (Mudah di-cluster & containerize) Sedang-Tinggi Sangat Tinggi (Fully Managed)

[!IMPORTANT] Untuk enterprise dengan kebutuhan strict compliance, Opsi A atau Opsi B wajib dipilih. Gunakan Opsi A jika stack backend eksisting Anda berbasis Go atau Node.js dan membutuhkan efisiensi resource yang ekstrem.


4. Prasyarat Sistem & Persiapan Lingkungan

Sebelum memulai instalasi, pastikan server produksi memenuhi spesifikasi minimal berikut:

  • OS: Ubuntu 22.04 LTS / Debian 12 / RHEL 9
  • CPU: Minimal 8 vCPU
  • RAM: Minimal 32 GB (Direkomendasikan 64 GB)
  • GPU: NVIDIA GPU (RTX 4090 / A10G / A100) dengan VRAM minimal 24GB, terinstall NVIDIA Driver & CUDA Toolkit 12.x
  • Storage: NVMe SSD minimal 100GB (untuk model weights dan vector index)

Verifikasi Driver GPU

Jalankan perintah berikut di terminal untuk memastikan GPU terdeteksi dengan benar:

nvidia-smi

Pastikan versi CUDA yang didukung sesuai dengan dependensi Ollama.


5. Panduan Implementasi Langkah demi Langkah

Step 1: Instalasi Ollama sebagai Systemd Service

Install Ollama secara resmi pada sistem Linux produksi:

curl -fsSL https://ollama.com/install.sh | sh

Konfigurasikan Ollama agar dapat diakses melalui jaringan lokal atau reverse proxy dengan mengedit file service systemd:

sudo nano /etc/systemd/system/ollama.service

Tambahkan konfigurasi lingkungan berikut di dalam blok [Service]:

[Service]
Environment="OLLAMA_HOST=0.0.0.0:11434"
Environment="OLLAMA_MODELS=/var/lib/ollama/models"
Environment="OLLAMA_NUM_PARALLEL=4"
Environment="OLLAMA_MAX_LOADED_MODELS=2"

Reload systemd dan restart layanan:

sudo systemctl daemon-reload
sudo systemctl restart ollama
sudo systemctl enable ollama

Pull model LLM yang akan digunakan (contoh: llama3 dan nomic-embed-text untuk embedding):

ollama pull llama3
ollama pull nomic-embed-text

Step 2: Menjalankan Qdrant Vector Database via Docker Compose

Buat direktori kerja untuk infrastruktur:

mkdir -p /opt/enterprise-rag && cd /opt/enterprise-rag

Buat file docker-compose.yml dengan konfigurasi production-ready:

version: '3.8'

services:
  qdrant:
    image: qdrant/qdrant:v1.9.0
    container_name: enterprise-qdrant
    restart: always
    ports:
      - "6333:6333"
      - "6334:6334"
    volumes:
      - qdrant_storage:/qdrant/storage
    environment:
      - QDRANT__SERVICE__GRPC_PORT=6334
    networks:
      - rag-net

networks:
  rag-net:
    driver: bridge

volumes:
  qdrant_storage:
    driver: local

Jalankan kontainer:

docker compose up -d

Step 3: Implementasi Backend Service (Node.js / TypeScript untuk RAG Pipeline)

Inisialisasi project TypeScript:

mkdir backend-rag && cd backend-rag
npm init -y
npm install typescript @types/node tsx --save-dev
npx tsc --init

Install client libraries yang dibutuhkan:

npm install @qdrant/js-client-rest axios dotenv

Buat file konfigurasi .env:

PORT=3000
OLLAMA_HOST=http://localhost:11434
QDRANT_HOST=http://localhost:6333
EMBEDDING_MODEL=nomic-embed-text
LLM_MODEL=llama3

Buat file utama index.ts untuk menangani proses embedding, vector storage, dan RAG generation:

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

dotenv.config();

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

const qdrant = new QdrantClient({ url: process.env.QDRANT_HOST || 'http://localhost:6333' });
const OLLAMA_URL = process.env.OLLAMA_HOST || 'http://localhost:11434';
const COLLECTION_NAME = 'enterprise_documents';

// Helper: Generate Embedding via Ollama
async function getEmbedding(text: string): Promise<number[]> {
  try {
    const response = await axios.post(`${OLLAMA_URL}/api/embeddings`, {
      model: process.env.EMBEDDING_MODEL || 'nomic-embed-text',
      prompt: text,
    });
    return response.data.embedding;
  } catch (error) {
    console.error('Error generating embedding:', error);
    throw error;
  }
}

// Endpoint: Ingest Dokumen
app.post('/api/ingest', async (req: Request, res: Response) => {
  try {
    const { id, text, metadata } = req.body;
    
    // Cek atau buat collection jika belum ada
    const collections = await qdrant.getCollections();
    const exists = collections.collections.some(c => c.name === COLLECTION_NAME);
    if (!exists) {
      await qdrant.createCollection(COLLECTION_NAME, {
        vectors: { size: 768, distance: 'Cosine' },
      });
    }

    const vector = await getEmbedding(text);

    await qdrant.upsert(COLLECTION_NAME, {
      wait: true,
      points: [
        {
          id: id,
          vector: vector,
          payload: { text, ...metadata },
        },
      ],
    });

    return res.status(200).json({ success: true, message: 'Document ingested successfully' });
  } catch (error: any) {
    return res.status(500).json({ success: false, error: error.message });
  }
});

// Endpoint: RAG Query
app.post('/api/query', async (req: Request, res: Response) => {
  try {
    const { query } = req.body;
    const queryVector = await getEmbedding(query);

    // Cari dokumen relevan di Qdrant
    const searchResult = await qdrant.search(COLLECTION_NAME, {
      vector: queryVector,
      limit: 3,
    });

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

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

    // Kirim ke Ollama LLM
    const llmResponse = await axios.post(`${OLLAMA_URL}/api/generate`, {
      model: process.env.LLM_MODEL || 'llama3',
      prompt: prompt,
      stream: false,
    });

    return res.status(200).json({
      success: true,
      answer: llmResponse.data.response,
      sources: searchResult.map(s => s.payload),
    });
  } catch (error: any) {
    return res.status(500).json({ success: false, error: error.message });
  });

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Enterprise RAG Service running on port ${PORT}`);
});

6. Bedah Kode & Penjelasan Detail Baris Kunci

  • OLLAMA_NUM_PARALLEL=4: Menentukan jumlah request paralel yang dapat diproses bersamaan oleh instance Ollama. Ini penting untuk mencegah antrean blocking pada beban traffic enterprise.
  • vectors: { size: 768, distance: 'Cosine' }: Parameter pada Qdrant yang mendefinisikan dimensi vektor output dari model nomic-embed-text (768 dimensi) dengan metode perhitungan kemiripan Cosine Similarity.
  • stream: false: Pada production endpoint, menonaktifkan streaming (false) mempermudah integrasi payload JSON standar dengan API gateway perusahaan, meskipun untuk pengalaman UI interaktif di web frontend, streaming (true) dengan Server-Sent Events (SSE) lebih disarankan.

7. Skenario Produksi & Studi Kasus Dunia Nyata

Dalam implementasi nyata di industri perbankan atau logistik dengan traffic tinggi (misal: 500 concurrent requests), arsitektur di atas harus dilindungi dengan Nginx Reverse Proxy, Rate Limiting, dan Load Balancing untuk instance Ollama.

Contoh konfigurasi Nginx (/etc/nginx/sites-available/rag-gateway.conf):

limit_req_zone $binary_remote_addr zone=rag_limit:10m rate=10r/s;

server {
    listen 80;
    server_name rag.internal.enterprise.com;
    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 / {
        limit_req zone=rag_limit burst=20 nodelay;
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_read_timeout 300s;
    }
}

8. Common Pitfalls, Anti-Patterns & Solusi

  1. Anti-Pattern: Memuat Terlalu Banyak Model Sekaligus di VRAM
    • Dampak: Terjadi Out-Of-Memory (OOM) pada GPU yang mengakibatkan crash server secara mendadak.
    • Solusi: Batasi parameter OLLAMA_MAX_LOADED_MODELS=1 atau 2 pada environment variable systemd Ollama.
  2. Pitfall: Chunk Size Dokumen Terlalu Besar
    • Dampak: Konteks yang dikirim ke LLM mencakup informasi yang tidak relevan, mengakibatkan penurunan akurasi jawaban.
    • Solusi: Gunakan ukuran chunking optimal antara 300 - 500 token dengan overlap sebesar 50 token.
  3. Mengabaikan Health Check pada Vector DB
    • Solusi: Selalu pasang auto-restart policy pada konfigurasi Docker Compose dan monitoring menggunakan Prometheus/Grafana.

9. Benchmark, Metrik Kinerja & Tuning Performa

Pengujian performa dapat dilakukan menggunakan tool beban seperti k6 untuk mensimulasikan ratusan pengguna konkuren yang mengirimkan query RAG secara bersamaan.

Contoh skrip pengujian load-test.js dengan k6:

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

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

export default function () {
  const url = 'http://localhost:3000/api/query';
  const payload = JSON.stringify({ query: 'Bagaimana prosedur klaim garansi perusahaan?' });
  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 < 1500ms': (r) => r.timings.duration < 1500,
  });
  sleep(1);
}

[!TIP] Tuning lanjutan dapat dilakukan dengan mengaktifkan quantisasi model (seperti GGUF Q4_K_M atau Q8_0) pada Ollama untuk mengurangi penggunaan VRAM hingga 50% tanpa mengorbankan akurasi generatif secara signifikan.


10. Checklist Penerapan Produksi & Kesimpulan

Sebelum merilis sistem Enterprise RAG ke lingkungan produksi penuh, pastikan checklist berikut terpenuhi:

  • Sistem operasi dan driver GPU (CUDA) telah diperbarui ke versi stabil terbaru.
  • Ollama dikonfigurasi sebagai systemd service dengan batasan VRAM yang aman.
  • Qdrant Vector Database berjalan di dalam isolasi container dengan volume persistent terbackup.
  • Nginx Reverse Proxy diamankan dengan SSL/TLS (Let's Encrypt / Internal CA) dan Rate Limiting aktif.
  • Logging dan monitoring (Prometheus/Grafana/ELK) terpasang untuk mendeteksi lonjakan latensi atau error.
  • Dilakukan uji beban (load testing) menggunakan k6 untuk memvalidasi kapasitas maksimal konkurensi.

Dengan mengikuti panduan komprehensif ini, Anda kini memiliki infrastruktur RAG berbasis local LLM yang aman, privat, berperforma tinggi, dan sepenuhnya berada di bawah kendali arsitektur enterprise Anda.

🏷️ Tags: #Devops #Rag #Vector Database #Ai Engineering #Ollama