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.
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:
- Ambil pertanyaan user (Input pertanyaan user)
- Cari artikel terdekat di FAISS (Melakukan query di vector, query sederhana banget)
- Buat sebuah chain untuk menggabungkan artikel yang relevan (Hasil chain inilah yang digunakan sebagai context di Prompt)
- 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):
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