4. Merancang Prompt yang Dapat Digunakan Kembali dengan Template
Di Bab 3, kita membangun CLI chat streaming yang berfungsi di mana prompt disematkan langsung dalam kode Python kita. Ini berfungsi untuk prototipe cepat, tetapi seiring aplikasi AI Anda berkembang, prompt yang di-hardcode menjadi mimpi buruk pemeliharaan. Bayangkan memperbarui logika prompt yang sama di beberapa file, atau mencoba melakukan A/B testing variasi prompt yang berbeda tanpa melakukan redeploy kode.
Bab ini mengajarkan Anda cara merancang prompt yang dapat digunakan kembali dan mudah dipelihara menggunakan sistem template LangChain. Anda akan belajar memisahkan logika prompt dari kode aplikasi, memanfaatkan pesan berbasis peran untuk kontrol LLM yang lebih baik, mengeksternalisasi prompt ke file YAML untuk kolaborasi tim, dan memvalidasi template sebelum eksekusi untuk menangkap kesalahan lebih awal.
Apa yang Dicakup Bab Ini (dan Apa yang Tidak):
Di bab ini, kita akan bekerja dengan template dan prompt secara manual—Anda akan secara eksplisit merender template menjadi pesan, kemudian mengirim pesan tersebut ke LLM menggunakan llm.invoke(). Pendekatan langsung ini membantu Anda memahami dengan tepat apa yang dilakukan template dan bagaimana cara kerjanya.
Di Bab 6, Anda akan belajar LCEL (LangChain Expression Language), yang memungkinkan Anda menyusun template dan LLM menjadi pipeline menggunakan operator |. Untuk saat ini, kita fokus pada fundamental template tanpa lapisan orkestrasi tersebut.
Di akhir bab ini, Anda akan memiliki sistem manajemen prompt yang kuat yang dapat diskalakan dari chatbot sederhana hingga workflow multi-agen yang kompleks.
4.1) Pemisahan Kepentingan: Memisahkan Kode dari Prompt
Mengapa Memisahkan Prompt dari Kode?
Ketika Anda meng-hardcode prompt langsung dalam logika aplikasi Anda, Anda menciptakan coupling yang ketat yang mengarah pada beberapa masalah:
Beban Pemeliharaan: Mengubah prompt memerlukan modifikasi kode Python, menjalankan tes, dan melakukan redeploy. Perubahan prompt biasanya terjadi jauh lebih sering daripada perubahan kode, membuat siklus modifikasi-kode-tes-redeploy ini sangat tidak efisien untuk apa yang seharusnya hanya pengeditan teks sederhana.
Tantangan Version Control: Ketika kode dan prompt dicampur bersama, version control menjadi sulit. Konflik merge lebih mungkin terjadi, dan setiap konflik memerlukan resolusi manual dan refactoring.
Friksi Kolaborasi: Anggota tim non-teknis (product manager, ahli domain) tidak dapat langsung mengedit prompt yang ada di file .py dan harus bergantung pada bantuan developer. Ketergantungan ini membuat siklus perbaikan prompt menjadi jauh lebih lambat.
Kompleksitas Testing: Menguji variasi prompt yang berbeda berarti menyalin kode, memodifikasi string, dan mengelola beberapa branch—membuat eksperimen menjadi lambat dan rentan kesalahan.
Pikirkan prompt seperti query SQL dalam aplikasi tradisional. Anda tidak akan meng-hardcode string SQL di seluruh kode Python Anda—Anda akan menggunakan ORM atau setidaknya memusatkan query. Prompt layak mendapat disiplin arsitektur yang sama.
Sistem Template LangChain
LangChain menyediakan kelas PromptTemplate dan ChatPromptTemplate untuk memisahkan struktur tetap prompt Anda dari data yang berubah. Tulis prompt Anda sekali dengan {placeholders}, kemudian masukkan nilai yang berbeda setiap kali—tidak perlu lagi membangun ulang prompt dengan f-string atau concatenation.
Sintaks dan Penggunaan Template
Sintaks Placeholder
Template menggunakan {variable_name} sebagai placeholder. Saat runtime, Anda menyediakan dictionary dengan kunci yang cocok:
from langchain_core.prompts import PromptTemplate
# Definisikan template dengan placeholder
template = PromptTemplate.from_template(
"Translate {content} from {source_lang} to {target_lang}"
)
# Isi placeholder dengan dictionary
result = template.invoke({
"content": "Hello world",
"source_lang": "English",
"target_lang": "Korean"
})
print(result.text)Output:
Translate Hello world from English to KoreanAturan Kunci:
- Nama placeholder harus cocok persis dengan kunci dictionary
- Semua placeholder harus disediakan (kunci yang hilang akan memunculkan
KeyError) - Kunci dictionary tambahan diabaikan
- Gunakan
invoke()untuk merender template dengan nilai Anda
PromptTemplate vs ChatPromptTemplate
PromptTemplate: Mengembalikan string biasa (dibungkus dalam StringPromptValue)
- Untuk text completion sederhana atau model legacy
- Output: String tunggal seperti
"Summarize: {content}"
ChatPromptTemplate: Mengembalikan pesan terstruktur dengan peran (dibungkus dalam ChatPromptValue)
- Untuk model chat modern (GPT-4, Claude, Gemini)
- Output: Pesan yang dipisahkan berdasarkan peran (system/user/assistant)
- Pilihan yang disukai: Lebih jelas dan lebih mudah dipelihara
Kapan menggunakan yang mana?
- Default ke
ChatPromptTemplateuntuk model chat—lebih jelas dan lebih mudah dipelihara - Gunakan
PromptTemplatehanya untuk completion sederhana atau ketika pemisahan peran tidak diperlukan
# PromptTemplate - output string tunggal
from langchain_core.prompts import PromptTemplate
template1 = PromptTemplate.from_template("Summarize: {content}")
result1 = template1.invoke({"content": "LangChain is a framework..."})
print(result1)Output:
text='Summarize: LangChain is a framework...'# ChatPromptTemplate - pesan berbasis peran
from langchain_core.prompts import ChatPromptTemplate
template2 = ChatPromptTemplate.from_messages([
("system", "You are a helpful assistant"),
("user", "{question}")
])
result2 = template2.invoke({"question": "What is LangChain?"})
print(result2)Output:
messages=[SystemMessage(content='You are a helpful assistant'), HumanMessage(content='What is LangChain?')]Template didefinisikan sekali. Anda dapat menggunakannya kembali dengan nilai yang berbeda tanpa memodifikasi definisi template. Baik PromptTemplate.invoke() maupun ChatPromptTemplate.invoke() mengembalikan nilai prompt yang siap dikirim langsung ke LLM.
Dari String Formatting ke Template
Mari kita refactor prompt yang di-hardcode untuk menggunakan template. Berikut versi "sebelum" dari Bab 3:
# Pendekatan hardcoded (gaya Bab 3)
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o-mini")
user_input = "Explain quantum computing"
# Logika prompt dicampur dengan kode
prompt = f"You are a helpful assistant. Answer this question: {user_input}"
response = llm.invoke(prompt)
print(response.content)Sekarang dengan template—menggunakan pendekatan langkah-demi-langkah yang akan kita praktikkan di seluruh bab ini:
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
# Template didefinisikan secara terpisah
template = ChatPromptTemplate.from_messages([
("system", "You are a helpful assistant."),
("user", "{user_input}")
])
# Logika aplikasi - eksekusi langkah-demi-langkah
llm = ChatOpenAI(model="gpt-4o-mini")
user_input = "Explain quantum computing"
# Langkah 1: Render template menjadi pesan
messages = template.invoke({"user_input": user_input})
# Langkah 2: Kirim pesan ke LLM
response = llm.invoke(messages)
print(response.content)Apa yang berubah?
- Definisi Template: Struktur prompt didefinisikan sekali dalam
template, terpisah dari logika eksekusi. - Sintaks Placeholder:
{user_input}adalah placeholder yang diisi saat runtime. - Eksekusi Langkah-demi-Langkah: Kita secara eksplisit merender template (
template.invoke()), kemudian mengirim hasilnya ke LLM (llm.invoke()). Proses dua langkah ini membantu Anda memahami apa yang sebenarnya dilakukan template. - Reusability:
templateyang sama dapat digunakan untuk pertanyaan pengguna apa pun tanpa modifikasi. - Struktur Pesan:
template.invoke()mengembalikanChatPromptValueyang diformat dengan benar yang diharapkan oleh LLM.
Mengapa Pendekatan Langkah-demi-Langkah?
Di seluruh bab ini, Anda akan melihat pola ini berulang kali:
messages = template.invoke(inputs) # Langkah 1: Render template
response = llm.invoke(messages) # Langkah 2: Kirim ke LLMKita menggunakan pendekatan dua langkah ini dengan sengaja untuk pembelajaran—ini menunjukkan dengan tepat apa yang dilakukan template: mengubah data input menjadi pesan terstruktur. Di Bab 6, Anda akan belajar pola produksi dunia nyata: menggabungkan langkah-langkah ini dengan pipeline LCEL (template | llm). Tetapi memahami setiap langkah secara terpisah terlebih dahulu membangun fondasi yang solid.
Validasi Template
Template menangkap kesalahan lebih awal. Jika Anda mereferensikan placeholder yang tidak ada, LangChain memunculkan error sebelum melakukan API call:
template = PromptTemplate.from_template("Summarize: {text}")
# Ini akan gagal - kunci 'text' hilang
try:
template.invoke({"content": "Some text"}) # Nama kunci salah
except KeyError as e:
print(f"Template error: {e}")Output:
Template error: "Input to PromptTemplate is missing variables {'text'}. Expected: ['text'] Received: ['content']Validasi ini terjadi pada waktu rendering template, bukan selama eksekusi LLM—menghemat waktu dan biaya API Anda.
4.2) Template Prompt yang Sadar Peran (System, User, Assistant)
Memahami Peran Pesan
LLM modern (GPT-4, GPT-5, Claude, Gemini) memahami struktur percakapan melalui peran pesan. Setiap pesan memiliki peran spesifik yang memberi tahu model cara menginterpretasinya.
Tiga Peran Inti:
System: Mendefinisikan bagaimana AI harus berperilaku
- Tujuan: Mengatur kepribadian AI, keahlian, dan aturan operasional
- Contoh: "You are a Python expert who writes concise code examples"
- Kapan berlaku: Diatur sekali di awal, memengaruhi semua respons
- Anggap sebagai: Manual instruksi AI
User: Mewakili input manusia
- Tujuan: Mengajukan pertanyaan atau membuat permintaan
- Contoh: "How do I read a file in Python?"
- Kapan berlaku: Setiap kali manusia mengirim pesan
- Anggap sebagai: Pertanyaan yang Anda ajukan
Assistant: Mewakili respons AI sebelumnya
- Tujuan: Menyediakan riwayat percakapan
- Contoh: "You can use the open() function to read files"
- Kapan berlaku: Ketika Anda memerlukan percakapan multi-turn
- Anggap sebagai: Memori AI tentang jawaban sebelumnya
Pesan System: Mekanisme Kontrol
Pesan system memberi tahu AI siapa dirinya dan bagaimana ia harus beroperasi—sebelum interaksi pengguna apa pun.
Apa yang Dapat Anda Kontrol:
- Keahlian: "You are a senior Python developer"
- Format Output: "Always respond in JSON format"
- Aturan Perilaku: "If unsure, say 'I don't know'"
- Gaya Respons: "Be concise and technical"
Mengapa Ini Penting:
Tanpa pesan system → respons generik dan verbose
Dengan pesan system → perilaku yang konsisten dan disesuaikan
Pesan System dalam Aksi
Mari kita lihat dampak nyata dari pesan system dengan membandingkan pertanyaan yang sama dengan dan tanpa pesan system. Perhatikan bagaimana respons berubah secara dramatis—tidak hanya dalam panjang, tetapi dalam nada, kompleksitas, dan pendekatan pengajaran.
Tanpa Pesan System:
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
template = ChatPromptTemplate.from_messages([
("user", "What is Python?")
])
llm = ChatOpenAI(model="gpt-4o-mini")
messages = template.invoke({})
response = llm.invoke(messages)
print(response.content)Output:
Python is a high-level, interpreted programming language known for its readability and simplicity.
It was created by Guido van Rossum and first released in 1991.
Python emphasizes code readability, allowing programmers to express concepts in fewer lines of code compared to languages such as C++ or Java.
Key features of Python include:
...Dengan Pesan System:
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
# Kontrol persona dan gaya output dengan pesan System
template = ChatPromptTemplate.from_messages([
("system", """You are a senior Python instructor with 15 years of teaching experience.
Your students are complete beginners who have never programmed before.
Teaching style:
- Use simple, everyday analogies
- Avoid technical jargon
- Show practical examples from daily life
- Be encouraging and patient"""),
("user", "What is Python?")
])
llm = ChatOpenAI(model="gpt-4o-mini")
messages = template.invoke({})
response = llm.invoke(messages)
print(response.content)Output:
Great question! Think of Python like a really helpful tool in your toolbox.
Just like a hammer or a screwdriver helps you build or fix things around the house, Python helps you create software or automate tasks on a computer.
Imagine you wanted to bake a cake.
You need a recipe to follow, right? In this analogy, Python is like that recipe.
It tells the computer what steps to take to achieve a goal, whether it's doing math, organizing files, or even running a game.
...Perbedaannya:
Tanpa Pesan System:
- AI menggunakan perilaku default-nya: sopan, informatif, tetapi generik
- Respons ensiklopedis dan formal—dioptimalkan untuk audiens luas
- Tidak ada persona yang konsisten: setiap respons mungkin bervariasi dalam nada dan gaya
- Tidak ada batasan: AI memutuskan sendiri seberapa detail atau teknis
Dengan Pesan System:
- AI mengikuti instruksi spesifik Anda: persona, gaya, dan aturan yang Anda definisikan
- Respons konsisten dan dapat diprediksi—setiap jawaban sesuai dengan persyaratan Anda
- Persona yang jelas dipertahankan: bertindak sebagai peran yang Anda tetapkan (guru, ahli, asisten)
- Batasan eksplisit diterapkan: format output, tingkat bahasa, dan batasan perilaku yang Anda tetapkan
Wawasan Kunci: Tanpa pesan system, Anda mendapatkan mode default AI. Dengan pesan system, Anda mendapatkan AI Anda—disesuaikan dengan kebutuhan aplikasi Anda. Pesan system mengubah AI dari alat serbaguna menjadi asisten khusus yang berperilaku persis seperti yang Anda inginkan, setiap saat.
Peran User dan Assistant: Membangun Percakapan
Pertanyaan Tunggal (User Saja):
template = ChatPromptTemplate.from_messages([
("system", "You are a Python expert."),
("user", "{question}")
])
llm = ChatOpenAI(model="gpt-4o-mini")
messages = template.invoke({"question": "How do I read a CSV?"})
response = llm.invoke(messages)Berfungsi baik untuk pertanyaan independen.
Multi-Turn dengan Konteks (User + Assistant):
Tanpa riwayat:
template = ChatPromptTemplate.from_messages([
("system", "You are a Python expert."),
("user", "How does it work?") # "it" = ???
])AI tidak tahu apa yang dimaksud dengan "it".
Dengan riwayat:
template = ChatPromptTemplate.from_messages([
("system", "You are a Python expert."),
("user", "What's the pandas library?"),
("assistant", "Pandas is a data analysis library."),
("user", "How does it work?") # Sekarang "it" = pandas
])Riwayat percakapan (pertanyaan user sebelumnya + respons assistant) menyediakan konteks. AI sekarang memahami "it" berarti pandas.
Contoh: Membangun Percakapan dengan Riwayat
Sekarang mari kita bangun contoh yang mengingat pertukaran sebelumnya. Fungsi ini mempertahankan riwayat percakapan dan meneruskannya ke AI dengan setiap pertanyaan baru:
llm = ChatOpenAI(model="gpt-4o-mini")
def chat_with_history(user_input: str, history: list):
messages = [("system", "You are a Python expert.")]
# Tambahkan riwayat
for msg in history:
messages.append((msg["role"], msg["content"]))
# Tambahkan input saat ini
messages.append(("user", user_input))
# Gunakan format mustache untuk menghindari error ketika konten mengandung {kurung kurawal}
template = ChatPromptTemplate.from_messages(messages, template_format="mustache")
formatted = template.format()
response = llm.invoke(formatted)
return response.content
# Penggunaan
history = []
# Turn 1
resp1 = chat_with_history("What's a Python dictionary?", history)
print(resp1)
history.append({"role": "user", "content": "What's a Python dictionary?"})
history.append({"role": "assistant", "content": resp1})
# Turn 2 - menggunakan konteks
resp2 = chat_with_history("Show an example.", history)
print(resp2)Aturan Urutan Pesan
LLM mengharapkan struktur percakapan spesifik: System → User → Assistant → User → Assistant → ...
Mengapa Urutan Ini?
Pola ini mencerminkan percakapan manusia-AI yang alami:
-
System datang pertama (opsional): Karena ini menetapkan aturan perilaku yang berlaku untuk seluruh percakapan, ini harus didefinisikan sebelum interaksi apa pun dimulai. Sama seperti Anda memberi briefing kepada seseorang sebelum mereka mulai bekerja, bukan di tengah tugas.
-
User kemudian Assistant bergantian: Dalam percakapan nyata, manusia berbicara (User), AI merespons (Assistant), manusia menindaklanjuti (User), AI merespons lagi (Assistant). Pola bergantian ini adalah bagaimana AI dilatih, jadi ia mengharapkan struktur ini.
-
Harus diakhiri dengan User: AI menghasilkan respons untuk pesan User terakhir. Jika percakapan diakhiri dengan Assistant, tidak ada yang bisa direspons oleh AI.
Contoh Valid:
# System + User tunggal
[("system", "..."), ("user", "...")]
# System + percakapan
[("system", "..."), ("user", "..."), ("assistant", "..."), ("user", "...")]Pola Bermasalah:
# Assistant sebelum User - AI bingung tentang konteks
[("system", "..."), ("assistant", "..."), ("user", "...")]
# AI melihat respons tanpa pertanyaan. Ia mungkin berhalusinasi pertanyaan apa
# yang dijawab ini, yang mengarah pada respons yang tidak relevan atau bingung.# Dua pesan User berturut-turut - respons AI hilang
[("system", "..."), ("user", "..."), ("user", "...")]
# AI tidak tahu pesan User mana yang harus direspons, atau mungkin menggabungkannya
# dengan canggung. Kehilangan alur percakapan.# Diakhiri dengan Assistant - tidak ada yang bisa direspons
[("system", "..."), ("user", "..."), ("assistant", "...")]
# Percakapan sudah selesai. AI tidak memiliki apa pun untuk dihasilkan karena tidak ada
# pertanyaan User yang tertunda. Kemungkinan akan menghasilkan error atau respons kosong.Poin Kunci: Pola-pola ini tidak selalu menyebabkan error keras, tetapi mereka membingungkan AI karena mereka melanggar logika percakapan yang dilatih padanya. AI mungkin menghasilkan respons, tetapi mereka akan tidak dapat diandalkan atau tidak masuk akal. Selalu ikuti pola yang diharapkan untuk perilaku yang dapat diprediksi.
Di Luar Riwayat Sederhana: Pola Produksi (Preview)
Catatan Penting: Pola riwayat percakapan yang baru saja Anda pelajari adalah fondasi yang bagus, tetapi sistem produksi menggunakan pendekatan yang lebih canggih.
Masalah dengan Riwayat Mentah:
Hanya meneruskan semua riwayat percakapan ke AI memiliki keterbatasan:
- Pemborosan token: Setiap pesan (bahkan yang lama) dihitung terhadap batas token Anda dan biaya
- Kehilangan fokus: AI mungkin terganggu oleh percakapan sebelumnya yang tidak relevan
- Tidak ada tugas eksplisit: AI menyimpulkan apa yang harus dilakukan dari riwayat, daripada menerima instruksi yang jelas
Pendekatan yang Lebih Baik:
Sistem produksi memisahkan konteks dari instruksi:
Pendekatan riwayat sederhana (yang baru kita pelajari):
messages = [
("system", "You are a Python expert."),
("user", "What's a dictionary?"),
("assistant", "A dictionary is a key-value data structure."),
("user", "Show an example.")
]Pendekatan produksi (akan datang di bab-bab selanjutnya):
messages = [
("system", "You are a Python expert."),
("user", """Context: The user previously asked about Python dictionaries and learned they are key-value structures.
Task: Provide a code example demonstrating dictionary usage.""")
]Perbedaannya:
- Riwayat mentah: AI melihat percakapan lengkap dan mencari tahu apa yang harus dilakukan
- Pola produksi: AI menerima konteks yang dirangkum + instruksi eksplisit
Manfaat pemisahan:
- Token lebih sedikit (biaya lebih rendah, respons lebih cepat)
- Perilaku lebih dapat diandalkan (instruksi yang jelas)
- Kontrol lebih baik (Anda memutuskan konteks apa yang penting)
Di mana Anda akan mempelajari ini:
- Bab 8: Mengelola state dan memori percakapan
- Bab 11: Contextual Retrieval (menggabungkan RAG dengan memori percakapan)
- Bab 16: Routing dinamis berdasarkan konteks percakapan
Untuk saat ini, memahami riwayat mentah sangat penting—ini adalah fondasi untuk pola-pola lanjutan ini. Tetapi ingat: apa yang baru saja Anda pelajari adalah alat pengajaran, bukan solusi akhir.
4.3) Mengeksternalisasi Prompt: Mengelola File Template (.yaml)
Mengapa Mengeksternalisasi Prompt?
Seiring aplikasi AI Anda berkembang, mengelola prompt dalam kode Python menjadi tidak praktis. Mengeksternalisasi prompt ke file YAML menyediakan:
Kolaborasi Non-teknis: Product manager, ahli domain, dan prompt engineer dapat mengedit file YAML tanpa menyentuh kode Python atau memahami konsep pemrograman.
Kejelasan Version Control: Lacak perubahan prompt secara terpisah dari perubahan kode. Tidak ada lagi commit campuran di mana tweak prompt dan pembaruan logika muncul bersama.
Prompt Spesifik Lingkungan: Prompt yang berbeda untuk development, staging, dan production tanpa perubahan kode.
A/B Testing: Uji variasi prompt dengan memuat file yang berbeda—tidak perlu perubahan kode.
Pikirkan file prompt YAML sebagai file konfigurasi dalam aplikasi tradisional—mereka mendefinisikan perilaku tanpa memerlukan perubahan kode atau redeploy.
Apa itu YAML?
YAML adalah format data yang dapat dibaca manusia yang umum digunakan untuk file konfigurasi. Jika Anda belum pernah melihat YAML sebelumnya, anggap saja sebagai alternatif yang lebih bersih untuk JSON—ia menggunakan indentasi alih-alih tanda kurung dan lebih mudah dibaca dan diedit.
Struktur Prompt YAML
LangChain mendefinisikan struktur file YAML standar untuk prompt. Mari kita lihat contohnya:
Contoh 1: Prompt tanpa variabel
Ketika prompt tidak memerlukan nilai runtime apa pun, atur input_variables ke list kosong:
# prompts/system_prompt.yaml
_type: prompt
input_variables: []
template: |
You are a helpful assistant.
Please answer in a friendly and encouraging tone.Simbol | memungkinkan Anda menulis teks multi-baris, dan line break dipertahankan.
Contoh 2: Prompt dengan variabel
Ketika prompt memerlukan nilai runtime, cantumkan mereka di input_variables:
# prompts/user_prompt.yaml
_type: prompt
input_variables:
- user_input
template: |
User question: {user_input}
Please provide a clear answer.Saat runtime, placeholder {user_input} diganti dengan nilai aktual.
Komponen kunci:
_type: prompt: Mengidentifikasi ini sebagai template promptinput_variables: Mencantumkan semua placeholder yang digunakan dalam template (list kosong[]jika tidak ada)template: Teks prompt aktual dengan{placeholders}
Memuat dan Menggunakan Prompt YAML
Pemuatan Dasar:
Sekarang mari kita muat file YAML yang kita buat dan gunakan dengan LLM:
from langchain_core.prompts import load_prompt, ChatPromptTemplate
from langchain_openai import ChatOpenAI
# Muat prompt dari file YAML
system_prompt_template = load_prompt("prompts/system_prompt.yaml")
user_prompt_template = load_prompt("prompts/user_prompt.yaml")
# Gabungkan prompt yang dimuat menjadi template chat
chat_template = ChatPromptTemplate.from_messages([
("system", system_prompt_template.template),
("user", user_prompt_template.template)
])
llm = ChatOpenAI(model="gpt-4o-mini")
# Langkah 1: Render template dengan nilai runtime
messages = chat_template.invoke({"user_input": "What is LangChain?"})
# Langkah 2: Kirim ke LLM
response = llm.invoke(messages)
print(response.content)Memverifikasi Template yang Dimuat:
Sebelum menggunakan template, verifikasi bahwa ia dimuat dengan benar:
from langchain_core.prompts import load_prompt
# Muat template
user_prompt_template = load_prompt("prompts/user_prompt.yaml")
# Periksa variabel apa yang diharapkan
print("Input variables:", user_prompt_template.input_variables)
# Lihat teks template
print("Template:", user_prompt_template.template)Output:
Input variables: ['user_input']
Template: User question: {user_input}
Please provide a clear answer.Kesalahan YAML Umum
Kesalahan 1: Indentasi tidak konsisten
YAML memerlukan indentasi yang konsisten (biasanya 2 spasi). Setiap level harus menggunakan jumlah spasi yang sama:
Salah:
_type: prompt
input_variables:
- user_input # Salah: item list harus diindentasi
- question # Salah: level indentasi campuranBenar:
_type: prompt
input_variables:
- user_input # Benar: kedua item pada level indentasi yang sama
- questionKesalahan 2: Ketidakcocokan placeholder
Placeholder dalam template harus cocok dengan input_variables:
Salah:
input_variables:
- user_input
template: "Question: {question}" # 'question' tidak ada di input_variables!Benar:
input_variables:
- user_input
template: "Question: {user_input}"LangChain akan memunculkan error jika placeholder tidak cocok dengan variabel yang dideklarasikan.
4.4) Melihat Preview dan Memvalidasi Template sebelum Eksekusi
Mengapa Preview Template?
Rekayasa prompt bersifat iteratif. Anda mengubah kata-kata, menyesuaikan struktur, menambahkan contoh—dan setiap iterasi memerlukan token API dan waktu. Melihat preview template sebelum eksekusi memungkinkan Anda:
Menghemat Waktu dan Uang: Tangkap kesalahan sebelum melakukan API call yang mahal.
Memverifikasi Kebenaran: Pastikan variabel diisi dengan benar dan formatting sesuai yang diharapkan.
Debug Secara Efisien: Lihat prompt yang tepat yang dikirim ke LLM, dengan semua variabel diisi dan formatting diterapkan.
Pikirkan preview template sebagai print debugging—Anda memeriksa state perantara sebelum eksekusi untuk memverifikasi kebenaran.
Preview Template Dasar
Memeriksa Struktur Template:
Sebelum menggunakan template dengan LLM, periksa strukturnya dan preview bagaimana ia merender dengan data sampel:
from langchain_core.prompts import ChatPromptTemplate
template = ChatPromptTemplate.from_messages([
("system", "You are a {role}."),
("user", "{user_input}")
])
# Preview struktur template
print("Input variables:", template.input_variables)
print("Message count:", len(template.messages))
# Preview dengan data sampel
prompt_value = template.invoke({
"role": "Python programming expert",
"user_input": "What is Python?"
})
print("\nPreview:")
for msg in prompt_value.to_messages():
print(f"{msg.type}: {msg.content}")Output:
Input variables: ['role', 'user_input']
Message count: 2
Preview:
system: You are a Python programming expert.
human: What is Python?Ini menunjukkan dengan tepat apa yang akan dikirim ke LLM, memungkinkan Anda memverifikasi prompt sebelum eksekusi.
Memvalidasi Template: Menangkap Variabel yang Hilang
Kesalahan template yang paling umum adalah variabel yang diperlukan hilang. Berikut fungsi validasi yang dapat digunakan kembali yang menangkap variabel yang hilang:
from langchain_core.prompts import ChatPromptTemplate
def preview_template(template: ChatPromptTemplate, inputs: dict):
"""Preview template dengan input yang diberikan, menangkap error."""
try:
prompt_value = template.invoke(inputs)
print("TEMPLATE PREVIEW")
print("=" * 60)
for i, msg in enumerate(prompt_value.to_messages(), 1):
print(f"Message {i} ({msg.type.upper()}):")
print(msg.content)
print("-" * 60)
except KeyError as e:
print(f"ERROR: {e}")
print(f"Required variables: {template.input_variables}")
# Penggunaan
template = ChatPromptTemplate.from_messages([
("system", "You are a {role}."),
("user", "{user_input}")
])
# Input valid
preview_template(template, {
"role": "Python programming expert",
"user_input": "What is Python?"
})
# Variabel hilang
preview_template(template, {
"user_input": "What is Python?" # 'role' hilang
})Output:
TEMPLATE PREVIEW
============================================================
Message 1 (SYSTEM):
You are a Python programming expert.
------------------------------------------------------------
Message 2 (HUMAN):
What is Python?
------------------------------------------------------------
ERROR: "Input to ChatPromptTemplate is missing variables {'role'}.
Expected: ['role', 'user_input'] Received: ['user_input']
...
Required variables: ['role', 'user_input']Workflow Validasi:
Berikut proses validasi template yang khas:
Proses iteratif ini membantu menangkap kesalahan sebelum LLM call yang mahal.
Checklist Pra-Eksekusi
Sebelum mengirim template ke production:
- Semua
input_variablesdideklarasikan di YAML/template - Data sampel merender tanpa error
- Prompt multi-baris ditampilkan dengan benar
- Placeholder cocok dengan nama variabel persis
- Uji dengan edge case (string kosong, teks panjang)
Ringkasan Bab:
Anda telah belajar merancang prompt yang mudah dipelihara dan dapat digunakan kembali menggunakan sistem template LangChain:
- Pemisahan Kepentingan: Pisahkan prompt dari kode untuk pemeliharaan dan iterasi yang lebih mudah
- Template Sadar Peran: Gunakan pesan system, user, dan assistant untuk interaksi LLM terstruktur dengan hierarki instruksi yang tepat
- Prompt yang Dieksternalisasi: Kelola prompt dalam file YAML untuk kolaborasi non-teknis dan version control
- Preview dan Validasi: Tangkap kesalahan lebih awal dan verifikasi template sebelum eksekusi
Langkah Selanjutnya:
Di Bab 5, Anda akan melihat bagaimana template memungkinkan pengambilan keputusan otonom dalam contoh agen preview. Kemudian di Bab 6, Anda akan belajar LCEL (LangChain Expression Language) untuk menyusun template ini menjadi pipeline yang kuat menggunakan operator |.