Merancang arsitektur untuk aplikasi LLM yang production-grade: pipeline RAG dari ingestion hingga reranking, pemilihan vector database dan siklus hidup embeddingnya, orkestrasi agent dengan guardrails, serta concern non-fungsional khas AI — latency budget, biaya per token, dan evaluasi

Setelah di episode 20 kalian merancang multi-tenancy untuk platform SaaS Acme — model pool/silo, RLS, dan propagasi tenant context — pada episode ini kita menjawab permintaan fitur berikutnya: asisten dukungan cerdas dan pencarian produk semantik. Keduanya bermuara ke satu hal: arsitektur sistem AI.
Bagi architect 2026, LLM bukan lagi demo menarik — ia adalah komponen sistem yang harus dirancang seperti komponen lainnya: dengan kontrak, batas kegagalan, latency budget, dan biaya yang terukur. Bedanya besar di satu titik: komponen ini non-deterministik. Output bisa berbeda untuk input sama, kualitas bergantung konteks, dan kegagalan sering halus (jawaban meyakinkan tapi salah) — bukan error keras yang mudah ditangkap. Seluruh desain episode ini mengakomodasi sifat itu.
Sebelum masuk pola, petakan dulu anatomi umum sistem LLM production:
Client → API Gateway → Orchestrator ─┬→ Retrieval (vector store)
├→ LLM provider (utama/fallback)
├→ Tools (aksi nyata: DB, API)
└→ Guardrails (validasi in/out)
Observability : trace prompt/response, cost,
latency, feedback userKonsekuensi arsitektural dari non-determinisme: setiap panggilan LLM harus ter-trace penuh (prompt versi apa, model apa, retrieval apa yang diambil) agar jawaban buruk bisa direproduksi dan diperbaiki. Tanpa observability khusus ini, debugging sistem AI = menebak-nebak.
RAG adalah pola fondasi: daripada mengandalkan ingatan model (yang usang dan halusinatif), kita retrieve dokumen relevan lalu menyuruh model menjawab berdasarkan konteks tersebut. Dua pipeline yang harus kalian rancang:
Sumber (docs, ticket, FAQ, catalog)
→ Ekstraksi & cleaning (normalisasi format)
→ Chunking (potong ±300-800 token, jaga utuh makna)
→ Embedding (model versi tertentu)
→ Simpan ke vector store + metadata (tenant_id!, sumber, versi)Keputusan chunking lebih penting daripada kelihatannya: chunk terlalu kecil kehilangan konteks, terlalu besar mengencerkan relevansi dan membengkakan token. Untuk studi kasus kita — dokumen FAQ dan riwayat ticket — chunking per bagian heading dengan sedikit overlap bekerja baik sebagai titik awal.
Query user → embed query → pencarian vektor (ANN) → idealnya digabung hybrid search (BM25 keyword + dense vector) → reranking top-k dengan model ringan → hasil terbaik masuk prompt → LLM menjawab dengan sitasi sumber.
Grounding + sitasi memberi dua manfaat sekaligus: halusinasi turun drastis karena model "menyontek" dari konteks, dan pengguna bisa memverifikasi jawaban — syarat wajar untuk domain dukungan pelanggan.
Pilihan penyimpanan vektor kalian punya spektrum:
| Opsi | Kelebihan | Kapan Memilih |
|---|---|---|
pgvector di PostgreSQL | Satu database untuk semua, filter SQL native, operasional akrab | Skala kecil-menengah; default mulai |
| Qdrant / Milvus / Weaviate | Index ANN tunable, throughput tinggi, fitur khusus vektor | Jutaan+ vektor atau latensi ketat |
| Managed (Pinecone dll.) | Zero ops, skala instan | Tim kecil tanpa kapasitas ops |
Dua jebakan arsitektural yang harus dicatat di ADR sejak awal:
tenant_id — melanjutkan disiplin episode 20 sampai ke komponen baru ini.Warning
Data tenant kalian akan masuk ke prompt. Terapkan data governance episode 19 juga di sini: PII difilter/sebelum dikirim ke provider pihak ketiga, retensi log prompt diatur, dan pilihan provider memperhitungkan kebijakan data training mereka. Prompt adalah data — perlakukan seperti field PII.
Ketika LLM tidak hanya menjawab tapi bertindak — cek status order, proses refund, update ticket — kita membangun agent: loop di mana model memilih tool, membaca hasilnya, dan memutuskan langkah berikutnya.
for (let step = 0; step < MAX_STEPS; step++) {
const plan = await llm.decide(context, toolResults);
if (plan.type === "final_answer") return validate(plan.answer);
assert(ALLOWED_TOOLS.has(plan.tool)); // allowlist ketat
const result = await tools[plan.tool](plan.args);
costTracker.add(plan); // budget per request
toolResults.push(result);
}
throw new BudgetExceededError(); // gagal aman, bukan loop abadiTiga guardrails yang membedakan agent production dari demo:
Pola orkestrasinya bertingkat: mulai dari single chain sederhana, router (klasifikasi intent lalu arahkan), hingga planner-executor untuk tugas kompleks. Prinsip trade-off kita konsisten sepanjang series: mulai dari yang paling sederhana yang bisa lulus evaluasi — agent multi-langkah adalah senjata terakhir, bukan pertama.
Aplikasi LLM punya rantai latensi baru. Contoh budget untuk asisten dukungan (target respons pertama di bawah 2 detik):
| Tahap | Budget | Catatan |
|---|---|---|
| Retrieval + rerank | 150 ms | ANN cepat; rerank model ringan |
| LLM time-to-first-token | 500 ms | Streaming wajib untuk UX |
| Stream penuh jawaban | 1-3 detik | Persepsi cepat lewat streaming |
| Fallback | — | Timeout → model fallback → pesan degradasi jujur |
Semantic cache (cache jawaban untuk pertanyaan mirip) dan prompt caching memangkas biaya dan latensi secara signifikan pada traffic FAQ yang berulang — pola caching episode 11 dalam wujud barunya.
Biaya adalah first-class quality attribute di sistem AI. Rumus sederhana yang harus ada di dashboard: cost_per_request = (input_tokens × harga_input + output_tokens × harga_output) per model — plus biaya embedding dan retrieval. Strategi penekannya berlapis: model kecil untuk klasikasi/routing, model besar hanya saat perlu; cache agresif; dan jangan kirim konteks lebih besar dari yang dibutuhkan.
Perubahan prompt atau ganti model = deploy tanpa test jika tidak ada eval harness: golden set pertanyaan-jawaban (50-200 kasus representatif), dijalankan otomatis tiap perubahan, dinilai dengan kombinasi penilaian programatik dan LLM-as-judge. Ini persis filosofi fitness function episode 22 yang akan datang — diterapkan pada komponen non-deterministik.
Mari ratifikasi desain AI platform Acme:
fitur_fase_1:
- asisten dukungan merchant (RAG atas docs + tickets)
- pencarian katalog semantik (embed product title+desc)
retrieval:
store: pgvector (satu DB, filter tenant_id native)
hybrid: BM25 + dense, rerank cross-encoder ringan
chunking: per heading, overlap 10%
embedding:
model: v1 tercatat di registry; reindex = migrasi
expand-contract (dual-index saat transisi)
orchestration:
pola: chain sederhana + router intent;
agent tool-calling hanya untuk aksi ticket
guardrails: allowlist tool, max_steps=6,
human approval refund > threshold
operasi:
streaming: wajib, TTFT target 500ms
semantic_cache: prefix per tenant, TTL 24 jam
eval: golden set 120 kasus, gate CI perubahan
prompt/model (skor min 85%)
observability: trace prompt/response/cost per request,
dimensi tenant_id wajib
governance:
pii: redaction sebelum keluar region
provider: no-training clause, DPA ditandatanganiPerhatikan bahwa hampir setiap entri adalah kelanjutan disiplin series ini: tenant filter (ep20), governance (ep19), identity (ep18), caching & budget (ep11), fitness gate (ep19). Sistem AI bukan disiplin terpisah — ia quality attributes lama dalam kemasan baru.
Tip
Sebelum optimasi apa pun (prompt engineering, model mahal, framework agent), pastikan retrieval-nya sudah bagus. Mayoritas jawaban buruk pada sistem RAG ternyata bukan salah model — konteks yang di-retrieve saja yang salah atau kurang. Ukur recall retrieval lebih dulu.
Inti yang harus dibawa pulang:
pgvector dulu), dengan dua aturan arsitektural: versi embedding adalah skema data, dan filter tenant wajib.Di episode 22 selanjutnya kita angkat katanya menjadi metode: architecture evaluation — bagaimana ATAM menilai arsitektur secara sistematis sebelum kode mahal ditulis, dan bagaimana fitness functions mengubah penilaian arsitektur dari opini sesaat menjadi gate otomatis di CI. Sampai jumpa!