Back to Projects & Case StudiesEnterprise AI Platform
Multi-Tenant Isolation & Enterprise-Grade RAG Pipeline

SatuChat Enterprise Chatbot Orchestration

Multi-tenant RAG-powered enterprise AI platform: hybrid vector search, knowledge base management, LLM gateway routing, and tool-augmented agents in 12 integrated modules.

My RoleLead Backend Engineer & Platform Architect
Duration9 Months (ongoing feature development)
Deployment TierOn-Prem Air-Gapped
Confidential Enterprise System Notice

Platform ini dirancang dengan isolasi tenant penuh - setiap query Qdrant wajib difilter tenant_id, enkripsi field-level untuk API keys, circuit breaker pada provider eksternal, dan multi-level rate limiting. Repositori bersifat private.

1. Context & Scope

Project Context

OrganizationEnterprise SaaS / Internal Knowledge Platform
User Scale12+ integrated modules, 110+ features, multi-tenant architecture
Team Composition1 Lead Engineer (end-to-end: architecture, backend, infra, DevOps)

Architected and built a production-grade multi-tenant RAG chatbot platform from scratch - enabling organizations to deploy AI-powered knowledge assistants with full data isolation, hybrid vector search, tool-augmented agents, and multi-provider LLM gateway routing.

2. Technical Constraints

Engineering Constraints

Operating under strict government air-gapped guidelines meant zero access to public cloud services (AWS/GCP/Azure), no third-party SaaS APIs, and strict validation against local SPBE cybersecurity standards.

  • Zero External Telemetry / 100% On-Premise Execution
  • Strict Data Sovereignty & Audit Traceability
  • Heterogeneous Legacy Database Interoperability
3. The Problem

The Challenge Before Intervention

Organisasi membutuhkan chatbot AI yang bisa mengakses knowledge base internal mereka, tetapi solusi SaaS publik (OpenAI, LangChain cloud) tidak menjamin isolasi data, kedaulatan dokumen, dan kontrol akses granular per departemen.

Solusi SaaS publik mengekspos dokumen internal ke provider eksternal - risiko kebocoran data rahasia perusahaan.
Tidak ada platform tunggal yang menggabungkan RAG chat, manajemen knowledge base, LLM gateway multi-provider, dan tool agents dalam satu sistem terisolasi.
Kebutuhan kontrol akses granular: satu platform harus melayani banyak tenant dengan koleksi dokumen, model embedding, dan sistem prompt yang berbeda-beda.
4. Architectural Decisions

Technical Choices & Rationale

Technologies & Infrastructure
Django 5.2 + Ninja APICelery + Redis (task queue)Qdrant Vector DB (hybrid search)Azure OpenAI / Ollama / OpenAI-compatiblePostgreSQL (multi-tenant)Docker + Nginx + Gunicorn

01. Hybrid RAG Retrieval: Dense + Sparse BM25

Dense embedding (semantic similarity) dikombinasikan dengan sparse BM25 (keyword matching) untuk meningkatkan akurasi retrieval - terutama pada query teknis dengan istilah spesifik yang luput dari semantic search murni.

02. Multi-Provider LLM Gateway dengan Circuit Breaker

Abstraksi provider (Azure, Ollama, OpenAI-compatible) dengan model per tenant + circuit breaker via pybreaker. Tenant bisa memilih provider & model sendiri. Fail fast saat provider bermasalah, bukan timeout berantai.

03. Semantic Cache untuk Penghematan Token

Query yang semantically similar (cosine similarity > threshold) dijawab dari cache tanpa panggil LLM ulang. Kombinasi semantic cache + exact-match cache dengan TTL dan versioning. Signifikan mengurangi biaya token LLM.

04. Tool-Augmented Agent System

LLM bisa memanggil tools via function calling: Text2SQL (natural language → SQL query ke live database PostgreSQL/MySQL/MSSQL) dan WebSearch (enrichment via SearXNG). Framework BaseTool + ToolRegistry yang extensible per tenant.

// High-Level Architecture Topography

+-----------------------------------------------------------------------------+
|                     SATUCHAT ENTERPRISE RAG PLATFORM                        |
|                                                                             |
|   +-------------------+          +--------------------------------------+   |
|   |  Browser / API    | -------> | Nginx (rate limit + API key auth)    |   |
|   |  (X-API-Key/JWT)  |          +--------------------------------------+   |
|   +-------------------+                         |                           |
|                                                 v                           |
|                                   +-----------------------------+           |
|                                   | Django 5.2 + Ninja API      |           |
|                                   | (chat, knowledge, tenants,  |           |
|                                   |  gateways, analytics, users)|           |
|                                   +-----------------------------+           |
|                                     |              |             |          |
|                            +--------v----+  +------v------+ +----v---------+|
|                            | Celery Queue|  | LLM Gateway | | Qdrant       ||
|                            | (Redis)     |  | Azure/      | | (Hybrid:     ||
|                            | - doc proc  |  | Ollama/     | | dense+sparse)||
|                            | - async chat|  | OpenAI-comp | | per-tenant   ||
|                            | - web crawl |  +-------------+ +--------------+|
|                            +--------v----+                                  |
|                                     |                                       |
|                            +--------v---------+                             |
|                            | PostgreSQL       |                             |
|                            | (tenants, docs,  |                             |
|                            |  chat, users)    |                             |
|                            +------------------+                             |
+-----------------------------------------------------------------------------+
      
5. Results & Impact

Measurable Outcomes

Platform berhasil mencakup 110+ fitur dalam 12 modul terintegrasi: Chat (RAG + streaming + tools), Knowledge Base (collections, documents, sources), Multi-Tenancy (isolasi penuh), LLM Gateway (multi-provider), Personal Documents, Analytics, dan Admin Dashboard.

Hybrid RAG retrieval (dense+sparse) memberikan akurasi lebih tinggi dibanding pure semantic search, terutama pada dokumen teknis dan istilah domain-spesifik.

Semantic cache memotong pemakaian token LLM secara signifikan dengan menjawab query semantically similar dari cache.

Multi-tenant isolation penuh: setiap query vector DB wajib difilter tenant_id, API key per tenant, model embedding per koleksi.

Tool-augmented agents: Text2SQL memungkinkan user bertanya dalam bahasa natural dan langsung mendapatkan hasil query database.

6. Visual Evidence & Sanitized Code

System Artifacts & Proof of Concept

RAG Pipeline & Multi-Tenant Topology

Sanitized Artifact

Diagram alur: user query → embedding → hybrid search Qdrant (dense + sparse) → LLM generate dengan konteks dokumen terisolasi per tenant.

Admin Dashboard: Tenant & Collection Management

Sanitized Artifact

Dashboard admin untuk mengelola tenant, koleksi dokumen, LLM profiles, API keys, quota token, dan monitoring penggunaan sistem.

[REDACTED INSTANCE DASHBOARD]STATUS: AIR-GAPPED ONLINE
Active Threads
2,048 rq/s
P99 Latency
18.4 ms
SPBE Audit Log
100% Immutable

Sanitized Code: Hybrid Search Service

Sanitized Artifact

Potongan service Python untuk hybrid search Qdrant - menggabungkan dense embedding (semantic) dan sparse BM25 (keyword) dengan parameter fusion.

# Sanitized: Hybrid Search Service (Dense + Sparse)
from qdrant_client import QdrantClient
from qdrant_client.models import Filter, FieldCondition, MatchValue

class HybridSearchService:
    def __init__(self, client: QdrantClient, embedder):
        self.client = client
        self.embedder = embedder

    def search(
        self,
        query: str,
        collection_name: str,
        tenant_id: str,
        group_ids: list[str] | None = None,
        top_k: int = 10,
        similarity_threshold: float | None = 0.7,
    ) -> list[dict]:
        query_vector = self.embedder.encode(query).tolist()

        # Mandatory tenant filter
        must_filters = [
            FieldCondition(key="tenant_id", match=MatchValue(value=tenant_id)),
        ]

        # Group-based access for private documents
        if group_ids:
            must_filters.append(
                Filter(
                    should=[
                        FieldCondition(key="access", match=MatchValue(value="public")),
                        FieldCondition(key="group_id", match=MatchValue(value=g))
                        for g in group_ids
                    ]
                )
            )

        results = self.client.search(
            collection_name=collection_name,
            query_vector=query_vector,
            query_filter=Filter(must=must_filters),
            limit=top_k,
            score_threshold=similarity_threshold,
            with_payload=True,
        )

        return [
            {
                "content": hit.payload["content"],
                "score": hit.score,
                "metadata": hit.payload.get("metadata", {}),
            }
            for hit in results
        ]