Journey to AI Engineer โ€” Part 5: Membangun Chatbot dengan RAG dan OpenAI

Setelah beberapa minggu tenggelam di dunia embeddings, index, dan prompt-prompt yang bikin otak kepanasan, akhirnya sampai juga di tahap seru: membuat chatbot sendiri untuk situs mkhuda.com! ๐Ÿคฎ

Kalau di part sebelumnya saya cerita tentang bagaimana prompt engineering bisa menyelesaikan 90% masalah bisnis (dan 10%-nya biasanya gara-gara typo ๐Ÿ˜…).

Kali ini kita akan bahas bagaimana saya mencoba membuat chatbot cerdas berbasis RAG (Retrieval-Augmented Generation) yang bisa menjawab pertanyaan berdasarkan isi blog saya ini.

Dari WordPress ke Vector Database

Semuanya dimulai dari ide sederhana:

โ€œBagaimana kalau pengunjung bisa ngobrol langsung dengan isi blog?โ€

Tapi nggak mungkin juga sih, lha wong visitornya saja sekarang secuil. Itu semua karna sejak era AI, blog-blog seperti ini kurang dilirik oleh netizen, visitor dropnya ampun-ampunan. Wkwkk ๐Ÿ˜ญ

Langkah 1, Ambil Data dari WordPress

Langkah pertama: menarik semua artikel dari database WordPress.
Saya ambil data dari tabel wp_posts, tentu dengan sedikit filter biar nggak ikut draft lama seperti โ€œhello worldโ€.

Bentuk query-nya seperti ini:

SELECT ID, post_title, post_content 
FROM wp_posts 
WHERE post_status='publish' AND post_type='post';

Setelah itu, datanya saya ubah ke format JSON, biar gampang diproses dan di-embedding.

Langkah 2, Embedding dan FAISS

Nah, bagian ini agak teknikal tapi tetap asik. (Aslinya puyeng)
Saya gunakan OpenAI Embeddings API (text-embedding-3-small) untuk mengubah tiap artikel jadi vector representation.

Model embedding ini masih sangat murah sebenarnya meskipun data kalian cukup besar,
Asalkan jangan sampai berGiga-giga aja

Bayangkan seperti ini: setiap artikel dikonversi jadi โ€œtitikโ€ di ruang 1.536 dimensi, karna text-embedding-3-small punya spek 1536 dimensi.

Misal ada dua artikel punya topik mirip (misalnya โ€œHTMX vs Alpine.jsโ€ dan โ€œHTML5 vs Mobile Nativeโ€œ), maka titiknya akan berdekatan, secara logika karna ada kata HTM.

Setelah semua vector siap, saya masukkan ke FAISS.
Btw, FAISS ini bisa dibilang semacam vector database yang bisa disimpan lokal (persistent storage). Teknologi ini dikembangkan oleh tim Facebook AI, dan namanya sendiri merupakan singkatan dari Facebook AI Similarity Search.

Langkah 3, Integrasi dengan gpt4o-mini

Setelah punya โ€œingatanโ€ berbentuk vector, sekarang waktunya bikin chatbot-nya. Saya integrasikan dengan model gpt-4o-mini. Alasannya karna chatbot ini sebenarnya tidak terlalu penting :D, bukan seperti chatbot marketing perusahaan.

Nah, ketika integrasi dengan LLM gpt-4o-mini inilah saya menyadari, bahwa basic prompt engineering yang kuat dibutuhkan. Karna tanpa system_prompt yang sesuai konteks, GPT tidak akan memahami apa maksud yang akan dicapai.

Ini adalah contoh potongan prompt system yang awalnya saya buat:

system_prompt = """
Kamu adalah asisten situs web mkhuda.com.

Setiap bagian konteks memiliki format seperti:
Judul: ...
URL: ...
Teks: ...

Gunakan URL dan judul yang tertera di konteks untuk membuat tautan HTML dengan format:
<a href="{{url}}" target="_blank">{{title}}</a>

Jika ada beberapa artikel relevan, tampilkan semuanya dalam daftar tautan.
Gunakan bahasa Indonesia yang santai tapi sopan.
"""

Untuk menghasilkan response yang sesuai, memang harus berdarah-darah dulu dengan membuat beberapa uji coba. Untungnya gpt-4o-mini ini tergolong murah meskipun Tokens yang kita kirim itu cukup banyak.

Langkah 4, Bikin Chatbot CLI Dulu

Sebelum melangkah lebih jauh kedunia per-widget-an. Saya coba dulu membuat CLI sederhana untuk menguji coba prompt, sekaligus retrieval si vector DB dengan LLM.

Secara urutan flow, sistem chatnya ini akan:

  1. Ambil pertanyaan user (Input pertanyaan user)
  2. Cari artikel terdekat di FAISS (Melakukan query di vector, query sederhana banget)
  3. Buat sebuah chain untuk menggabungkan artikel yang relevan (Hasil chain inilah yang digunakan sebagai context di Prompt)
  4. Kirim semuanya ke LLM OpenAI untuk menghasilkan jawaban yang natural

Kurang lebih seperti ini, implementasi Python-nya:

llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.7, api_key=api_key)
retriever = vectorstore.as_retriever(search_type="similarity", search_kwargs={"k": 4})
....
system_prompt =""""isi sesuai system prompt""""
prompt = ChatPromptTemplate.from_messages([
    ("system", system_prompt),
    ("human", "Konteks:\n{context}\n\nPertanyaan: {input}")
])
....
combine_docs_chain = create_stuff_documents_chain(
    llm=llm,
    prompt=prompt,
    document_variable_name="context"  # default "context", eksplisitkan saja
)
...
context_text = format_docs_with_meta(docs)
context_doc = [Document(page_content=context_text)]
result = combine_docs_chain.invoke({
   "context": context_doc,
   "input": q
})

Dan hasilnya?
Chatbot mkhuda.com bisa menjawab pertanyaan seperti ini (sesuai apa yang pernah saya tulis di blog tentunya):

Chatbot CLI mkhuda.com

Secara response GPT, berkat adanya prompting di system_prompt, dan juga ketepatan FAISS dalam hal similarity search, membuat pertanyaan dan jawaban akan nyambung sesuai data yang telah kita build sebelumnya di vektor FAISS.


Baik, di part selanjutnya saya akan mencoba mengintegrasikan semua itu menjadi sebuah chatbot di blog ini. Apabila berhasil, maka kalian akan melihat chat widget di kanan bawah. Jika tidak? ya berarti zonk!

Terima kasih & Stay tuned

Muhammad K Huda: A non exhausted blogger person within fullstack engineer (spicy food), open source religion, self-taught driver and maybe you know or don't like it. Simply says, Hello from Me!
Related Post