function ($q) { $q->orderBy('created_at', 'asc'); } ]) ->where('id_user', auth()->id()) ->where('status_chat', 'aktif') ->first(); $messages = $chatSession ? $chatSession->messages : collect([]); return view( 'halaman-chatbot', compact( 'chatSession', 'messages' ) ); } // ========================= // KIRIM CHAT // ========================= public function kirim(Request $request) { $pesanUser = $request->input('message'); $userId = Auth::id(); // ========================= // CEK SESSION CHAT // ========================= $chatSession = DB::table('chat_sessions') ->where('id_user', $userId) ->where('status_chat', 'aktif') ->first(); // kalau belum ada session if (!$chatSession) { $sessionId = DB::table('chat_sessions') ->insertGetId([ 'id_user' => $userId, 'status_chat' => 'aktif', 'started_at' => now(), 'ended_at' => now() ]); } else { $sessionId = $chatSession->id_sessions; session([ 'chat_session_id' => $sessionId ]); } // ========================= // SIMPAN CHAT USER // ========================= DB::table('chat_messages')->insert([ 'id_sessions' => $sessionId, 'sender' => 'user', 'message' => $pesanUser, 'created_at' => now() ]); // ========================= // DEFAULT // ========================= $rekomendasiProperti = []; $balasan = 'Maaf kak, terjadi kesalahan 😥'; // ========================= // API KEY // ========================= $apiKey = env('GROQ_API_KEY'); if (!$apiKey) { return response()->json([ 'reply' => 'API key tidak ditemukan!', 'options' => [], 'properti' => [] ]); } // ========================= // DATA PROPERTI // ========================= $properti = DB::table('properti') ->where('status_unit', 'tersedia') ->select( 'id_properti', 'nama_properti', 'jenis_properti', 'kategori_properti', 'tipe_properti', 'harga_properti', 'luas_bangunan', 'luas_tanah', 'stok_unit' ) ->get(); $propertiJson = json_encode($properti); // ========================= // SYSTEM PROMPT // ========================= $systemPrompt = " Kamu adalah CaraniBot, customer service virtual PT. Carani Bhanu Balakosa. Gaya bicara: - Santai - Natural - Ramah - Seperti admin chat WhatsApp - Jangan terlalu formal - Jangan terlalu kaku - Gunakan emoji seperlunya 😊 - Panggil user dengan 'kak' jika cocok ATURAN PENTING: - DILARANG menggunakan markdown. - DILARANG menggunakan tanda bintang seperti * atau **. - DILARANG membuat bullet list. - DILARANG membuat format poin-poin. - Balasan harus seperti chat biasa. - Gunakan kalimat natural dan mengalir. - Jangan terlalu panjang. Jika user baru menyebut ingin cari rumah/properti: - Jangan langsung memberi rekomendasi properti. - Tanya kebutuhan user dulu secara natural. Contoh gaya yang BENAR: 'Siap kak 😊 Boleh tahu budget dan lokasi yang kakak inginkan?' Contoh gaya yang SALAH: '* Budget? * * Lokasi? *' Kamu bisa membantu: - konsultasi properti - rekomendasi rumah - KPR - subsidi - lokasi properti - harga rumah - proses pembelian - pertanyaan umum pelanggan Data properti: $propertiJson Jika ingin merekomendasikan properti, gunakan format: [REKOMENDASI:id] Contoh: [REKOMENDASI:1,2] "; try { $client = new \GuzzleHttp\Client(); $response = $client->post( 'https://api.groq.com/openai/v1/chat/completions', [ 'headers' => [ 'Content-Type' => 'application/json', 'Authorization' => 'Bearer ' . $apiKey ], 'json' => [ 'model' => 'llama-3.1-8b-instant', 'max_tokens' => 500, 'messages' => [ [ 'role' => 'system', 'content' => $systemPrompt ], [ 'role' => 'user', 'content' => $pesanUser ] ] ] ] ); $result = json_decode( $response->getBody(), true ); $balasan = $result['choices'][0]['message']['content'] ?? 'Tidak ada balasan'; // ========================= // CEK TAG REKOMENDASI // ========================= if ( preg_match( '/\[REKOMENDASI:([\d,]+)\]/', $balasan, $matches ) ) { $ids = explode(',', $matches[1]); $rekomendasiProperti = DB::table('properti') ->whereIn( 'id_properti', $ids ) ->where( 'status_unit', 'tersedia' ) ->select( 'id_properti', 'nama_properti', 'jenis_properti', 'kategori_properti', 'tipe_properti', 'harga_properti', 'luas_bangunan', 'luas_tanah', 'stok_unit' ) ->get() ->toArray(); // hapus tag dari chat $balasan = trim( preg_replace( '/\[REKOMENDASI:[\d,]+\]/', '', $balasan ) ); } } catch (\Exception $e) { $balasan = 'Maaf kak, server lagi gangguan 😥'; $rekomendasiProperti = []; } // ========================= // SIMPAN BALASAN BOT // ========================= DB::table('chat_messages')->insert([ 'id_sessions' => $sessionId, 'sender' => 'bot', 'message' => $balasan, 'properti_data' => json_encode($rekomendasiProperti), 'created_at' => now() ]); // ========================= // RESPONSE JSON // ========================= return response()->json([ 'reply' => $balasan, 'options' => [], 'properti' => $rekomendasiProperti ]); } // ========================= // HAPUS RIWAYAT CHAT // ========================= public function hapusRiwayat() { $userId = auth()->id(); $session = DB::table('chat_sessions') ->where('id_user', $userId) ->where('status_chat', 'aktif') ->first(); if ($session) { DB::table('chat_messages') ->where('id_sessions', $session->id_sessions) ->delete(); DB::table('chat_sessions') ->where('id_sessions', $session->id_sessions) ->delete(); } return response()->json([ 'success' => true ]); } // PESAN TERBARU public function pesanTerbaru(Request $request) { $sessionId = session('chat_session_id'); if (!$sessionId) { return response()->json([ 'messages' => [] ]); } $lastId = $request->last_id ?? 0; $messages = \App\Models\ChatbotMessage::where( 'id_sessions', $sessionId ) ->where( 'id_messages', '>', $lastId ) ->orderBy( 'created_at', 'asc' ) ->get(); \Log::info([ 'session_chatbot' => $sessionId, 'last_id' => $lastId, 'jumlah_pesan' => $messages->count(), 'messages' => $messages->pluck('sender') ]); return response()->json([ 'messages' => $messages ]); } }