Tutorial Membangun RAG Chatbot Lokal dengan Ollama dan LangChain.js
AP
Adrian Prat

Dipublikasikan 20 Agustus 2026

Tutorial Membangun RAG Chatbot Lokal dengan Ollama dan LangChain.js

Retrieval Augmented Generation atau RAG telah menjadi standar de facto untuk membangun chatbot yang tidak hanya cerdas, tapi juga akurat dan terkini. Alih-alih bergantung sepenuhnya pada pengetahuan model bahasa yang terbatas pada data latih, RAG memungkinkan sistem mengambil informasi relevan dari knowledge base eksternal sebelum menghasilkan respons. Artikel ini akan memandu kamu membangun chatbot RAG sederhana yang berjalan sepenuhnya di lokal menggunakan Ollama untuk menjalankan LLM, LangChain.js sebagai orchestration framework, dan ChromaDB sebagai vector store. Tidak ada biaya API pihak ketiga, tidak ada khawatir privasi data, dan kamu punya kendali penuh atas seluruh pipeline.

Arsitektur RAG terdiri dari dua fase utama: indexing dan retrieval. Pada fase indexing, dokumen sumber dipecah menjadi chunk, diubah menjadi vektor embedding menggunakan model bahasa, lalu disimpan di vector database. Pada fase retrieval, pertanyaan user diubah menjadi vektor yang sama, lalu sistem mencari chunk paling relevan untuk dijadikan konteks bagi LLM. Kombinasi Ollama, LangChain.js, dan ChromaDB menyederhanakan kedua fase ini menjadi workflow yang bisa dijalankan di laptop biasa tanpa koneksi internet setelah setup awal selesai.

Persiapan Environment dan Instalasi

Pastikan Node.js versi 18 atau lebih baru sudah terpasang. Kamu juga membutuhkan Ollama yang bisa diunduh dari ollama.com/download. Setelah terpasang, jalankan perintah berikut untuk mengunduh model embedding dan text generation:

ollama pull nomic-embed-text
ollama pull llama3.2

Buat direktori proyek dan inisialisasi project Node.js:

mkdir rag-chatbot-local && cd rag-chatbot-local
npm init -y
npm install langchain @langchain/community @langchain/ollama chromadb

Model nomic-embed-text akan bertugas mengubah teks menjadi vektor numerik, sementara llama3.2 akan menjadi otak yang menghasilkan respons natural berdasarkan konteks yang diberikan. Kombinasi ini dirancang untuk berjalan efisien di hardware consumer tanpa memerlukan GPU dedicated.

Inisialisasi ChromaDB dan Embedding

Buat file index.js dan mulai dengan mengimpor modul yang diperlukan serta menginisialisasi embedding model dari Ollama. ChromaDB akan berjalan dalam mode in-memory untuk tutorial ini, meski untuk production kamu bisa mengkonfigurasinya sebagai persistent client.

import { OllamaEmbeddings } from '@langchain/ollama';
import { Chroma } from '@langchain/community/vectorstores/chroma';
import { Ollama } from '@langchain/ollama';
import { RecursiveCharacterTextSplitter } from 'langchain/text_splitter';

const embeddings = new OllamaEmbeddings({
  model: 'nomic-embed-text',
  baseUrl: 'http://localhost:11434',
});

const vectorStore = await Chroma.fromExistingCollection(embeddings, {
  collectionName: 'docs',
  url: 'http://localhost:8000',
});

Pastikan Ollama berjalan di background sebelum menjalankan script. Kamu bisa memverifikasinya dengan ollama list yang akan menampilkan model yang sudah terunduh. Jika Ollama tidak berjalan, embedding initialization akan gagal dengan connection refused error.

Chunking dan Indexing Dokumen

Siapkan beberapa file teks sebagai knowledge base. Bisa berupa dokumentasi produk, FAQ, atau artikel referensi. LangChain menyediakan RecursiveCharacterTextSplitter yang secara cerdas memecah dokumen besar menjadi chunk berukuran seragam dengan overlap antar chunk untuk menjaga konteks.

const splitter = new RecursiveCharacterTextSplitter({
  chunkSize: 500,
  chunkOverlap: 50,
});

const docs = await splitter.createDocuments([fs.readFileSync('knowledge.txt', 'utf8')]);
await Chroma.fromDocuments(docs, embeddings, {
  collectionName: 'docs',
  url: 'http://localhost:8000',
});

Ukuran chunk 500 karakter dengan overlap 50 karakter adalah starting point yang umum digunakan. Untuk dokumen teknis yang padat istilah, kamu mungkin perlu mengecilkan chunk size agar setiap potongan tetap fokus pada satu topik spesifik. Sebaliknya, untuk dokumen naratif yang membutuhkan konteks luas, chunk size yang lebih besar bisa menghasilkan retrieval yang lebih bermakna.

Membangun RAG Chain

Setelah dokumen terindex, bangun chain yang menggabungkan retrieval dan generation. LangChain menyederhanakan ini dengan RetrievalQAChain yang secara otomatis menangani formatting prompt dan injeksi konteks.

const model = new Ollama({
  model: 'llama3.2',
  baseUrl: 'http://localhost:11434',
  temperature: 0.3,
});

const retriever = vectorStore.asRetriever({ k: 3 });
const chain = RetrievalQAChain.fromLLM(model, retriever);

const response = await chain.invoke({
  query: 'Apa kebijakan pengembalian produk kami?',
});

console.log(response.text);

Parameter k: 3 berarti sistem akan mengambil 3 chunk paling relevan untuk dijadikan konteks. Nilai ini bisa disesuaikan berdasarkan kompleksitas pertanyaan dan ukuran chunk. Temperature 0.3 memastikan respons tetap faktual dan tidak terlalu kreatif, sebuah pengaturan yang penting untuk aplikasi customer support atau knowledge base internal.

Integrasi ke Interface Chat

Untuk membuatnya interaktif, bungkus chain dalam loop sederhana yang membaca input dari terminal. Kamu bisa mengembangkannya lebih lanjut menjadi web interface menggunakan framework seperti Hono atau Express.

import readline from 'readline';

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

console.log('RAG Chatbot siap. Ketik pertanyaan atau "exit" untuk keluar.');

rl.on('line', async (input) => {
  if (input.toLowerCase() === 'exit') {
    rl.close();
    return;
  }
  const res = await chain.invoke({ query: input });
  console.log('Bot:', res.text);
});

Loop ini memungkinkan pengujian interaktif tanpa perlu membangun frontend terlebih dahulu. Setelah puas dengan akurasi respons, kamu bisa mengekspos chain melalui API endpoint dan menghubungkannya dengan web interface atau aplikasi mobile.

Optimasi dan Best Practices

Beberapa optimasi bisa diterapkan untuk meningkatkan kualitas RAG. Pertama, gunakan MultiQueryRetriever untuk menghasilkan variasi pertanyaan dari input user, meningkatkan peluang menemukan chunk relevan. Kedua, implementasikan re-ranking dengan model cross-encoder untuk menyaring hasil retrieval sebelum dikirim ke LLM. Ketiga, pertimbangkan metadata filtering jika knowledge base memiliki struktur hierarkis seperti kategori produk atau departemen.

Pastikan juga untuk memantau latency. Retrieval dari ChromaDB lokal biasanya di bawah 100ms, tapi generation dengan LLM bisa memakan waktu beberapa detik tergantung ukuran model dan hardware. Untuk produksi, pertimbangkan model yang lebih kecil seperti phi3 atau gemma2 yang menawarkan trade-off yang lebih baik antara kecepatan dan kualitas untuk tugas-tugas spesifik.

Sumber: Dokumentasi LangChain.js, Ollama, ChromaDB