Dalam Bagian IV dari seri ini, kami melakukan benchmark terhadap latensi LAN lokal dan mesh Tailscale untuk grav-ai-chatbot, membuktikan bahwa transport jaringan sangat cepat dan andal.
Namun, segera setelah model pemrosesan logika seperti
qwen3.5:2bdi-deploy ke produksi, pengguna mulai melaporkan bug yang membingungkan: mengirim pesan sederhana seperti"hello"berulang kali mengembalikan pesan error umum:"Terjadi kesalahan koneksi tidak terduga. Silakan coba lagi nanti."
Investigasi kegagalan ini mengungkapkan interaksi mendalam antara pemrosesan logika CoT, batasan
max_tokensrendah, perilaku KV-cache Ollama, dan pertahanan klien (client-side fallback). Berikut adalah apa yang sebenarnya terjadi di bawah kapak dan bagaimana kami memperbaikinya langkah demi langkah.
1. Penyebab Utama: Kebocoran Monolog CoT & Error Konten Kosong
Model reasoning lokal modern (seperti Qwen 3.5 dan DeepSeek R1) mengirimkan respons melalui dua saluran dalam API Ollama:
reasoning: Alur pemikiran internal / monologue (Thinking Process:).content: Jawaban akhir teks yang dimaksudkan untuk pengguna.
Ketika pengguna mengirim input pendek seperti "hello", model qwen3.5:2b memulai monolog eksternya:
{
"id": "chatcmpl-801",
"choices": [
{
"finish_reason": "length",
"index": 0,
"message": {
"content": "",
"reasoning": "Thinking Process:
1. **Analyze the Request:**
* Input: \"hello\"
* Intent: Salam dan memeriksa kehadiran...
2. **Determine Appropriate Response:**...
3. **Drafting the Response:**..."
}
}
],
"usage": {
"completion_tokens": 512,
"prompt_tokens": 18,
"total_tokens": 530
}
}
Ini menghasilkan dua mode kegagalan kritis:
- Ekspensi Budget Token: Ketika
max_tokensrendah (misalnya 256/512 token), model menghabiskan seluruh budget di"reasoning", mencapaifinish_reason: "length"dengan"content": "". PHP client (OpenAiCompatibleClient.php) mengevaluasi!empty($content)sebagaifalse, menyebabkanChatbotHandler.phpmemunculkan pesan error custom umum ke pengunjung. - Monolog Kebocoran: Ketika
max_tokenslebih besar, model menyelesaikan reasoning dan mengeluarkan teks monologue mentah (Thinking Process: 1. Analyze...), yang disimpan dalam riwayat percakapan dan ditampilkan di antarmuka chat.
2. Kegagalan KV-Cache: Bagaimana Masking Prompt Caching Menyembunyikan Masalah
Selama pengujian pengembangan, mengulang input test identik ("hello") menghasilkan hasil yang berbeda-beda. Kadang gagal segera, kadang mengembalikan jawaban cepat.
Inkonsistensi ini disebabkan oleh KV-Cache (Ollama) di Ollama:
- Penggunaan Konteks: Ollama menggunakan state KV pre-computed untuk prefix sistem + user prompt identik.
- Latensi Tersembunyi & Perilaku: Ketika mengulang input yang sama, Ollama melompati evaluasi prompt penuh dan menyajikan token cache. Ini menyembunyikan alokasi token sungguhan selama pengujian manual berulang.
- Kebutuhan Validasi Cache: Untuk menyingkap perilaku model asli, pengujian harus dilakukan menggunakan prompt unik (atau dengan restart Ollama untuk membersihkan KV-cache).
Beragamkan input prompt saat benchmark sangat penting untuk mengisolasikan perilaku CoT yang sebenarnya.
3. Apa yang Kami Sebenarnya Implementasi: Arsitektur & Perubahan Kode
Untuk mengatasi kebocoran CoT, ekspensi token, dan menyediakan kontrol admin konfigurable, kami melakukan update spesifik pada kodebase berikut:
A. Sistem Prompt Rules Custom & Prepending (ChatbotHandler.php)
Kami menambahkan opsi konfigurasi custom_system_prompt di Grav Admin dan plugin settings.
Di ChatbotHandler.php, kami mengimplementasikan logika untuk menyelesaikan sistem prompt rules:
- Jika
custom_system_promptterisi di Grav Admin, plugin menjalankan instruksi custom pengguna. - Jika
custom_system_promptkosong/lebar, otomatis jatuh ke aturan default system yang tepat:Jawabkan user secara langsung. Jangan termasuk proses pemikiran, langkah-langkah reasoning, scratchpad, atau monologue internal Anda. Pertahankan total respons di bawah sekitar {max_response_chars} karakter. - Placeholder
{max_response_chars}dinamis interpolasi batas soft setting.
Prepending Rules ke Context Situs
Crucialnya, sistem prompt rules diletakkan di paling atas dari context system prompt ($siteContext) sebelum dokumentasi RAG atau konteks situs terikat:
// Kode yang diimplementasikan dalam ChatbotHandler.php
$customSystemPrompt = trim($this->config['custom_system_prompt'] ?? '');
$maxChars = (int)($this->config['max_response_chars'] ?? 1000);
$defaultSystemPrompt = "Jawabkan user secara langsung. Jangan termasuk proses pemikiran, langkah-langkah reasoning, scratchpad, atau monologue internal Anda. Pertahankan total respons di bawah sekitar {max_response_chars} karakter.";
$template = !empty($customSystemPrompt) ? $customSystemPrompt : $defaultSystemPrompt;
$systemRule = str_replace('{max_response_chars}', (string)$maxChars, $template);
// PREPEND SYSTEM RULES TO SITE CONTEXT
$siteContext = trim($systemRule . "
" . $siteContext);