← Back to Cecep Azhar
Cecep Azhar #rag#retrieval-augmented-generation#vector-search#embeddings#ai-agent

RAG Architecture: Cara AI Agent Mendapatkan Pengetahuan dari Dokumen

Cecep Saeful Azhar • 16 Oct 2026
RAG Architecture: Cara AI Agent Mendapatkan Pengetahuan dari Dokumen
Pelajari arsitektur RAG untuk AI Agent agar bisa mendapatkan pengetahuan dari dokumen bisnis kamu. Panduan practical dengan contoh kode Go.

Mengapa RAG Dibutuhkan?

LLM seperti GPT-4 memiliki pengetahuan yang luas tapi terbatas pada data training mereka. Bagaimana jika kamu ingin AI Agent menjawab pertanyaan berdasarkan dokumen internal perusahaan kamu? Di sinilah RAG (Retrieval-Augmented Generation) hadir.

Dari pengalaman saya membangun AI Agent untuk beberapa perusahaan di Bandung, RAG adalah pattern yang paling sering dibutuhkan. Baik untuk knowledge base internal, dokumentasi produk, maupun FAQ customer.

Pipeline RAG yang Saya Gunakan

Ada tiga tahap utama dalam RAG pipeline: indexing, retrieval, dan generation. Berikut implementasinya dalam Go:

type RAGPipeline struct {
    embedder  Embedder
    vectorDB  VectorStore
    llm       LLMClient
    chunker   DocumentChunker
}

// Tahap 1: Indexing - Memproses dokumen menjadi embeddings
func (r *RAGPipeline) IndexDocument(ctx context.Context, doc Document) error {
    // Chunk document menjadi bagian-bagian kecil
    chunks := r.chunker.Chunk(doc.Content, 512, 50) // 512 tokens, 50 overlap
    
    for i, chunk := range chunks {
        embedding, err := r.embedder.Embed(ctx, chunk)
        if err != nil {
            return fmt.Errorf("failed to embed chunk %d: %w", i, err)
        }
        
        err = r.vectorDB.Upsert(ctx, Point{
            ID:     fmt.Sprintf("%s_%d", doc.ID, i),
            Vector: embedding,
            Payload: map[string]interface{}{
                "content":   chunk,
                "doc_id":   doc.ID,
                "metadata": doc.Metadata,
            },
        })
        if err != nil {
            return err
        }
    }
    return nil
}

Retrieval yang Efektif

Retrieval adalah tahap kritis. Kita perlu mencari chunks yang paling relevan dengan query user. Saya menggunakan hybrid search (combining semantic + keyword search) untuk hasil yang lebih baik:

// Tahap 2: Retrieval
func (r *RAGPipeline) Retrieve(ctx context.Context, query string, topK int) ([]Chunk, error) {
    queryEmbedding, err := r.embedder.Embed(ctx, query)
    if err != nil {
        return nil, err
    }
    
    results, err := r.vectorDB.Search(ctx, SearchRequest{
        Vector:    queryEmbedding,
        TopK:     topK,
        Threshold: 0.7, // Minimum similarity score
    })
    if err != nil {
        return nil, err
    }
    
    // Rerank results menggunakan cross-encoder
    reranked := r.reranker.Rerank(query, results)
    
    return reranked, nil
}

Generation dengan Context

Tahap terakhir adalah generate jawaban menggunakan retrieved chunks sebagai context:

// Tahap 3: Generation
func (r *RAGPipeline) Query(ctx context.Context, question string) (string, error) {
    chunks, err := r.Retrieve(ctx, question, 5)
    if err != nil {
        return "", err
    }
    
    // Build context dari retrieved chunks
    context := ""
    for i, chunk := range chunks {
        context += fmt.Sprintf("[Sumber %d]: %s\n\n", i+1, chunk.Content)
    }
    
    prompt := fmt.Sprintf(`Berdasarkan sumber berikut, jawab pertanyaan user secara akurat.
Jika jawaban tidak ada di sumber, katakan bahwa kamu tidak memiliki informasi tersebut.

Sumber:\n%s\n\nPertanyaan: %s`, context, question)
    
    return r.llm.Generate(ctx, prompt)
}

Tips Optimization

Dari beberapa implementasi RAG yang sudah saya lakukan, ada tips penting: gunakan chunk size yang tepat (tidak terlalu kecil dan tidak terlalu besar), implement metadata filtering untuk domain-specific retrieval, dan jangan lupa untuk evaluate retrieval quality secara berkala menggunakan metrik seperti precision dan recall.

← More articles from Cecep Azhar Central Content Hub Home →