Sistem kami melakukan satu hal dengan sangat baik: Mengubah pertanyaan dalam bahasa alami menjadi panggilan API.
Para penggunanya adalah analis, manajer akun, dan pemimpin operasi. Mereka tahu data apa yang mereka butuhkan, tetapi mengumpulkannya secara manual harus mengambil dari empat dasbor, dua alat BI, dan sebuah pembangun laporan Salesforce. Dengan sistem kami, mereka hanya perlu mengetik permintaan dalam bahasa Inggris sederhana. Permintaan seperti “Kompilasi laporan volume penjualan untuk Januari hingga Maret 2026 untuk wilayah Timur Laut, terbagi berdasarkan kota” akan diterjemahkan menjadi panggilan API yang dapat direspons oleh sistem:
json
{
“description”: “Pengguna meminta volume penjualan untuk rentang tanggal yang diberikan, berikut panggilan API untuk mendapatkan respons”,
“api_call”: “/api/sales_volume”,
“post_body”: {
“start_date”: “2026-01-01”,
“end_date”: “2026-03-31”,
“region”: “northeast”
}
}
Bagian selanjutnya dari alur kerja adalah rekayasa konvensional. Sistem ini mengirimkan panggilan ke backend yang tepat — kami memiliki integrasi dengan portal laporan internal, Salesforce, dan beberapa layanan buatan sendiri — menerapkan model bahasa besar (LLM) untuk menyaring dan membentuk respons, kemudian mengantarkannya melalui email, sebagai dokumen Drive, atau menampilkannya sebagai grafik di browser.
Menjelang pertengahan 2025, sistem ini menghasilkan beberapa ratus laporan setiap bulan. Laporan-laporan ini dikonsumsi oleh pimpinan dan analis serta disebarkan kepada pemangku kepentingan eksternal. Ini telah menjadi cara standar bagi sebagian besar tim untuk menarik data ad-hoc.
Kontrak antara LLM dan sisa sistem adalah objek JSON yang terstruktur seperti yang dijelaskan di atas.
Kami membangunnya pada Claude Sonnet 3.5 pada awal 2025. Kami melakukan upgrade ke 3.7 dan ke 4.0 tanpa masalah. Ketika Sonnet 4.5 dirilis, kami mulai merasa terlalu percaya diri mengenai kestabilan dan prediktabilitas LLM dalam menangani masalah yang kami anggap sederhana. Upgrade model telah menjadi rutinitas, seperti memperbarui versi minor dari pustaka yang berfungsi dengan baik.
Namun, setelah kami meluncurkan 4.5, untuk persentase permintaan yang signifikan, model mulai menggabungkan isi post_body ke dalam kolom deskripsi. Dua mode kesalahan muncul.
Pertama, parameter penyaring tidak mencapai API. Sistem kami membaca post_body sebagai sumber kebenaran untuk payload permintaan, dan kolom itu kembali kosong. Panggilan API dibuat tanpa filter rentang tanggal atau wilayah. Tergantung pada API yang dipanggil, backend bisa jadi mengembalikan volume penjualan untuk seluruh waktu atau semua wilayah, atau mengembalikan kesalahan 500.
Kedua, model mulai mengajukan pertanyaan klarifikasi dalam responsnya. Ini adalah hal baru. Versi sebelumnya selalu mengambil pendekatan terbaik terhadap permintaan yang ambigu dan mengembalikan objek terstruktur. Sonnet 4.5, yang lebih berhati-hati, kadang-kadang merespon dengan pertanyaan sebagai gantinya. Sistem kami tidak memiliki jalur untuk ini. Ia dibangun dengan asumsi bahwa setiap pemanggilan model akan menghasilkan panggilan API. Tidak ada komponen manusia dalam loop dan tidak ada status untuk menampung permintaan yang belum selesai. Ini menyebabkan sistem di hilir gagal dalam berbagai cara.
Kami kembali ke 4.0. Proses ini lebih sulit dari yang seharusnya: Antara peluncuran 4.0 dan 4.5, tim kami telah menambahkan integrasi API baru, semuanya diperiksa dengan 4.5. Mengembalikan model berarti harus memverifikasi ulang setiap integrasi tersebut dengan 4.0 di bawah tekanan waktu.
Mengapa disiplin rekayasa tradisional gagal di sini
Rekayasa perangkat lunak berdiri di atas kemampuan untuk membatasi efek dari sebuah perubahan. Ketika Anda meng-upgrade driver atau pustaka, Anda membaca catatan rilis untuk melihat apakah ada perubahan yang merusak. Uji unit membatasi apa saja yang mungkin telah berubah. Anda dapat memanfaatkan sifat berikut: Sistem yang diubah cukup deterministik sehingga perilakunya dapat diprediksi, atau setidaknya diambil sampel cukup untuk memberi Anda keyakinan. Jangkauan dampaknya dibatasi oleh konstruksi.
Sistem berbasis LLM melanggar asumsi ini. Komponen yang menghasilkan output Anda tidak berada di bawah kendali Anda. Anda tidak bisa membandingkan versi model dari 4.0 ke 4.5. Ini adalah penggantian total dari fungsionalitas yang menjadi dasar sistem Anda.
Inilah yang kami maksud dengan jangkauan ledakan tak terbatas: perubahan yang efek hilirnya tidak dapat dicantumkan sebelumnya karena ruang input (bahasa alami) dan mode kesalahan (apa pun yang bisa dilakukan model berbeda) tidak terbatas.
Anatomi dari kegagalan
Analisis pasca kejadian mengungkapkan bahwa prompt kami selalu kurang ditentukan. Kami telah memberitahu model untuk mengembalikan objek JSON dengan tiga kolom. Kami telah menjelaskan tiap kolom. Namun kami tidak secara eksplisit menyatakan bahwa deskripsi harus berupa string dalam bahasa alami dan tidak boleh mengandung representasi terstruktur dari kolom lainnya.
Versi sebelumnya dari model menyimpulkan batasan ini dari konteks. Sonnet 4.5, yang tampaknya lebih “membantu” dalam pilihan formatnya, memutuskan bahwa meminta klarifikasi atau memberikan badan permintaan dalam deskripsi membuat respons lebih berguna. Dari sudut pandang model, ini adalah interpretasi yang wajar dari instruksi yang ambigu. Namun, ini melanggar asumsi di mana sistem kami dibangun.
Kesalahan itu bukan pada model. Kesalahan terletak pada asumsi kami bahwa model akan tetap mengisi celah spesifikasi kami seperti yang selalu dilakukannya. Tiga upgrade yang berhasil telah melatih kami untuk percaya bahwa celah tersebut aman.
Mode output terstruktur dan API penggunaan alat seharusnya menangkap kesalahan spesifik ini di tingkat skema. Namun, kami tidak menggunakannya karena alasan rekayasa di luar ruang lingkup artikel ini. Tapi skema hanya membatasi sintaksis, bukan semantik. Skema tidak dapat menentukan bahwa pertanyaan klarifikasi tidak boleh muncul dalam sebuah sistem tanpa jalur untuk klarifikasi, atau bahwa rentang tanggal tidak boleh secara diam-diam kembali ke semua waktu. Skema menyelesaikan separuh masalah yang lebih mudah.
Arsitektur evals-first
Disiplin yang menutup celah ini adalah dengan memperlakukan suite evaluasi — bukan prompt — sebagai spesifikasi formal dari sistem. Prompt adalah implementasi dari spesifikasi. Model adalah interpreter. Evals adalah spesifikasi itu sendiri, dan setiap perubahan model atau prompt hanya valid jika memenuhi syarat tersebut.
Dalam praktiknya, eval adalah triple: Sebuah input, sebuah properti yang harus dipenuhi output, dan fungsi penilaian. Untuk sistem kami, eval yang seharusnya telah menangkap regresi 4.5 terlihat seperti ini:
python
def test_description_contains_no_serialized_payload(response):
desc = response[“description”].lower()
forbidden = [“curl”, “post_body”, “{“, “http://”, “https://”]
assert not any(token in desc for token in forbidden), \
f”deskripsi mengungkapkan konten terstruktur: {response[‘description’]}”
Beberapa ratus properti semacam ini, beberapa ditulis tangan untuk invarian penting yang已 diketahui, beberapa dihasilkan sebagai tes regresi dari lalu lintas produksi yang nyata, dan beberapa dinilai oleh LLM-sebagai-juri untuk kualitas yang lebih kabur seperti nada, menjadi pintu gerbang. Upgrade model dan perubahan prompt seharusnya dianggap sebagai pull request yang harus mengubah suite menjadi hijau sebelum mereka dapat digabungkan.
Evals mahal untuk dibangun dan dipelihara. Mereka dapat melenceng seiring dengan perubahan produk Anda. Skor LLM-sebagai-juri memperkenalkan variansi sendiri dalam hasil. Dan suite hanya dapat menangkap mode kegagalan yang telah Anda pikirkan untuk ditentukan — Anda tidak bisa eval untuk mendapatkan keselamatan terhadap kategori kegagalan yang belum pernah Anda bayangkan. Kami belajar pelajaran ini dengan cara yang sulit: Tidak ada orang di tim kami yang pernah menulis pernyataan yang mengatakan “kolom deskripsi tidak boleh mengandung perintah curl,” karena tidak ada yang berpikir bahwa model akan menaruhnya di sana.
Evals bukanlah solusi yang sempurna. Mereka memberi Anda kemampuan untuk membatasi jangkauan ledakan dari sebuah perubahan dalam satu-satunya cara yang tersedia ketika fungsi yang mendasari adalah kotak hitam: Dengan melakukan sampling yang padat terhadap respons input-output yang benar-benar Anda pedulikan, dan menolak untuk menerapkan ketika perilaku itu berubah.
Peta jalan
Komunitas rekayasa belum mengembangkan kumpulan pengetahuan untuk menulis evals yang efektif. Tidak ada standar yang diterima secara luas untuk apa yang dimaksud dengan ‘cakupan’ dalam ruang input bahasa alami. Sistem CI/CD tidak dirancang untuk membatasi hasil tes probabilistik. Seiring agen mengambil lebih banyak pekerjaan otonom — menulis kode, memindahkan uang, menjadwalkan perubahan infrastruktur — kesenjangan antara “model telah lulus tes awal kami” dan “kami tahu apa yang akan dilakukan sistem ini dalam produksi” menjadi masalah teknik sentral selama beberapa tahun ke depan.
Tim yang menutup celah tersebut akan menjadi mereka yang menghentikan perlakuan eval sebagai pemikiran setelah kualitas dan mulai memperlakukannya sebagai spesifikasi aktual dari apa yang sistem mereka.

