> ## Documentation Index
> Fetch the complete documentation index at: https://docs.neosantara.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# RAG dengan ChromaDB

> Bangun pipeline Retrieval-Augmented Generation (RAG) lokal menggunakan Neosantara Embeddings dan ChromaDB.

Retrieval-Augmented Generation (RAG) menggabungkan pencarian vektor semantik dengan model generasi bahasa. Dokumen eksternal diubah menjadi representasi vektor floating-point, disimpan dalam basis data vektor, lalu bagian yang paling relevan disuntikkan ke dalam prompt model sebagai konteks referensi faktual.

<img src="https://mintcdn.com/neosantara/sW3WMdUoyvHZIoOA/images/alur-rag.webp?fit=max&auto=format&n=sW3WMdUoyvHZIoOA&q=85&s=50d484cbfd16d964b02e9f64d924b8bb" alt="Alur RAG" width="1292" height="813" data-path="images/alur-rag.webp" />

## Alur Eksekusi Cepat

```python theme={"theme":{"light":"ayu-dark","dark":"catppuccin-latte"}}
import os
import chromadb
from chromadb import Documents, EmbeddingFunction, Embeddings
from openai import OpenAI

client = OpenAI(
    base_url="https://api.neosantara.xyz/v1",
    api_key=os.environ["NEOSANTARA_API_KEY"]
)

class NeosantaraEmbeddingFunction(EmbeddingFunction):
    def __call__(self, input: Documents) -> Embeddings:
        response = client.embeddings.create(
            model="nusa-embedding-0001",
            input=input
        )
        return [d.embedding for d in response.data]

# Inisialisasi vector store ChromaDB lokal
chroma_client = chromadb.Client()
collection = chroma_client.create_collection(
    name="manual_mobil",
    embedding_function=NeosantaraEmbeddingFunction()
)

# Tambahkan dokumen referensi
collection.add(
    documents=[
        "Suhu AC mobil diatur menggunakan kenop tengah. Putar searah jarum jam untuk menaikkan suhu.",
        "Transmisi otomatis: Posisi P untuk parkir, R untuk mundur, N untuk netral, D untuk melaju.",
        "Layar sentuh 12 inci mengontrol navigasi, media hiburan, dan diagnostik kendaraan."
    ],
    ids=["doc1", "doc2", "doc3"]
)

# Ambil dokumen relevan dan generate jawaban
query = "Bagaimana cara mengubah suhu mobil?"
results = collection.query(query_texts=[query], n_results=1)
relevant_context = results["documents"][0][0]

response = client.chat.completions.create(
    model="deepseek-v4.1-flash",
    messages=[
        {"role": "system", "content": f"Jawab pertanyaan berdasarkan konteks berikut:\n\n{relevant_context}"},
        {"role": "user", "content": query}
    ]
)

print(response.choices[0].message.content)
```

<CardGroup cols={2}>
  <Card title="Embeddings Capability" icon="binary" href="/id/gateway/capabilities/embeddings">
    Spesifikasi parameter endpoint /v1/embeddings dan format output vektor.
  </Card>

  <Card title="Katalog Model Embedding" icon="list" href="/id/gateway/models">
    Daftar model embedding yang tersedia seperti nusa-embedding-0001 dan nv-embed-v1.
  </Card>
</CardGroup>

## Implementasi Step-by-Step

<Steps>
  <Step title="Instalasi Dependensi">
    Instal pustaka Python yang diperlukan untuk [OpenAI SDK](https://openai.com/?utm_source=neosantara-docs\&utm_medium=referral) dan [ChromaDB](https://www.trychroma.com/?utm_source=neosantara-docs\&utm_medium=referral):

    ```bash theme={"theme":{"light":"ayu-dark","dark":"catppuccin-latte"}}
    pip install -U openai chromadb numpy pandas
    ```

    <CodeGroup>
      ```bash Bash / zsh icon="terminal" theme={"theme":{"light":"ayu-dark","dark":"catppuccin-latte"}}
      export NEOSANTARA_API_KEY="nsk_your_api_key_here"
      ```

      ```env .env icon="file-code" theme={"theme":{"light":"ayu-dark","dark":"catppuccin-latte"}}
      NEOSANTARA_API_KEY=nsk_your_api_key_here
      ```

      ```powershell PowerShell icon="terminal" theme={"theme":{"light":"ayu-dark","dark":"catppuccin-latte"}}
      $env:NEOSANTARA_API_KEY="nsk_your_api_key_here"
      ```
    </CodeGroup>
  </Step>

  <Step title="Definisikan Embedding Function Kustom">
    ChromaDB mendukung custom embedding function untuk menghubungkan panggilan embedding ke endpoint `/v1/embeddings` Neosantara:

    ```python theme={"theme":{"light":"ayu-dark","dark":"catppuccin-latte"}}
    import chromadb
    from chromadb import Documents, EmbeddingFunction, Embeddings
    from openai import OpenAI
    import os

    client = OpenAI(
        base_url="https://api.neosantara.xyz/v1",
        api_key=os.environ["NEOSANTARA_API_KEY"]
    )

    EMBEDDING_MODEL = "nusa-embedding-0001"
    CHAT_MODEL = "deepseek-v4.1-flash"

    class NeosantaraEmbeddingFunction(EmbeddingFunction):
        def __call__(self, input: Documents) -> Embeddings:
            response = client.embeddings.create(
                model=EMBEDDING_MODEL,
                input=input
            )
            return [d.embedding for d in response.data]
    ```
  </Step>

  <Step title="Indeks Dokumen ke Koleksi Chroma">
    Simpan sekumpulan dokumen ke dalam koleksi ChromaDB. Koleksi akan otomatis memanggil fungsi embedding Neosantara untuk menghasilkan vektor 768 dimensi:

    ```python theme={"theme":{"light":"ayu-dark","dark":"catppuccin-latte"}}
    def setup_knowledge_base(docs, collection_name="sop_perusahaan"):
        chroma_client = chromadb.Client()
        try:
            chroma_client.delete_collection(name=collection_name)
        except Exception:
            pass

        db = chroma_client.create_collection(
            name=collection_name,
            embedding_function=NeosantaraEmbeddingFunction()
        )

        for i, text in enumerate(docs):
            db.add(
                documents=[text],
                ids=[f"id_{i}"]
            )
        return db
    ```
  </Step>

  <Step title="Pencarian Vektor & Grounded Generation">
    Cari bagian yang paling relevan dengan kueri pengguna menggunakan pencarian kemiripan kosinus, lalu minta model chat menghasilkan jawaban yang didasari konteks tersebut:

    ```python theme={"theme":{"light":"ayu-dark","dark":"catppuccin-latte"}}
    def generate_grounded_answer(query: str, db, n_results: int = 2):
        # 1. Retrieval
        results = db.query(query_texts=[query], n_results=n_results)
        matched_docs = results["documents"][0] if results and results["documents"] else []
        
        if not matched_docs:
            return "Informasi relevan tidak ditemukan dalam basis pengetahuan."

        context_text = "\n---\n".join(matched_docs)

        # 2. Augmented Generation
        prompt = (
            "Anda adalah asisten berbasis data referensi. Jawab pertanyaan pengguna "
            "hanya menggunakan informasi dalam bagian referensi di bawah ini. "
            "Jika jawaban tidak termuat dalam referensi, jawab terus terang bahwa "
            "informasi tersebut tidak tersedia.\n\n"
            f"REFERENSI:\n{context_text}\n\n"
            f"PERTANYAAN: {query}\n\n"
            "JAWABAN:"
        )

        response = client.chat.completions.create(
            model=CHAT_MODEL,
            messages=[{"role": "user", "content": prompt}],
            temperature=0.2
        )
        return response.choices[0].message.content
    ```
  </Step>
</Steps>

## Kode Lengkap & Pengujian

Berikut skrip lengkap yang menguji pertanyaan yang ada di dalam dokumen maupun pertanyaan di luar basis pengetahuan:

```python rag_chroma_complete.py theme={"theme":{"light":"ayu-dark","dark":"catppuccin-latte"}}
import os
import chromadb
from chromadb import Documents, EmbeddingFunction, Embeddings
from openai import OpenAI

client = OpenAI(
    base_url="https://api.neosantara.xyz/v1",
    api_key=os.environ["NEOSANTARA_API_KEY"]
)

EMBEDDING_MODEL = "nusa-embedding-0001"
CHAT_MODEL = "deepseek-v4.1-flash"

class NeosantaraEmbeddingFunction(EmbeddingFunction):
    def __call__(self, input: Documents) -> Embeddings:
        response = client.embeddings.create(
            model=EMBEDDING_MODEL,
            input=input
        )
        return [d.embedding for d in response.data]

documents = [
    (
        "Sistem Kontrol Suhu: Suhu kabin dikontrol melalui kenop konsol tengah. "
        "Putar searah jarum jam untuk menaikkan suhu dan berlawanan arah untuk mendinginkan. "
        "Mode defrost meniupkan udara hangat langsung ke kaca depan untuk menghilangkan kabut."
    ),
    (
        "Layar Sentuh & Navigasi: Layar sentuh 12 inci menyediakan peta real-time, "
        "koneksi Bluetooth ponsel, dan pengaturan profil pengemudi. "
        "Tekan ikon roda gigi di kanan atas untuk membuka pengaturan diagnostik."
    ),
    (
        "Transmisi & Pengereman: Mobil menggunakan transmisi elektrik satu percepatan. "
        "Injak pedal rem penuh sebelum menekan tombol Start/Stop mesin."
    )
]

# Siapkan basis data vektor
chroma_client = chromadb.Client()
collection = chroma_client.create_collection(
    name="car_manual",
    embedding_function=NeosantaraEmbeddingFunction()
)

for idx, doc in enumerate(documents):
    collection.add(documents=[doc], ids=[f"doc_{idx}"])

def ask_rag(question: str):
    print(f"\nPertanyaan: {question}")
    results = collection.query(query_texts=[question], n_results=1)
    passage = results["documents"][0][0]

    response = client.chat.completions.create(
        model=CHAT_MODEL,
        messages=[
            {
                "role": "system",
                "content": "Jawab pertanyaan secara ringkas dan presisi hanya berdasarkan konteks referensi yang diberikan."
            },
            {
                "role": "user",
                "content": f"Konteks Referensi:\n{passage}\n\nPertanyaan: {question}"
            }
        ],
        temperature=0.1
    )
    print(f"Jawaban AI : {response.choices[0].message.content}")

if __name__ == "__main__":
    ask_rag("Bagaimana cara menghilangkan kabut di kaca depan?")
    ask_rag("Berapa ukuran layar sentuh kendaraan?")
    ask_rag("Apakah kendaraan memiliki fitur pembuat kopi?")
```

<Tip>
  Gunakan parameter `temperature=0.1` atau `temperature=0` pada tahap generasi untuk meminimalkan halusinasi dan memastikan jawaban strictly grounded pada dokumen yang diambil.
</Tip>

<Note>
  Model `nusa-embedding-0001` menghasilkan vektor embedding 768 dimensi dengan harga gratis/termasuk dalam kuota Neosantara.
</Note>

## Referensi Terkait

* [RAG dengan Cloudflare Vectorize](/id/guides/rag-cloudflare-vectorize)
* [Prompt Caching & Optimasi Biaya](/id/guides/prompt-caching)
* [Endpoint Embeddings](/id/gateway/capabilities/embeddings)
* [Katalog Model & Token Pricing](/id/gateway/models)


## Related topics

- [Embeddings](/id/gateway/capabilities/embeddings.md)
- [Chat Completions](/id/gateway/chat-completions.md)
- [Katalog Model](/id/gateway/models.md)
- [Prompt Caching & Optimasi Biaya](/id/guides/prompt-caching.md)
