user() ->chatConversations() ->with('messages') ->latest() ->first(); if (! $conversation) { $conversation = $request->user()->chatConversations()->create([ 'title' => 'Chat AI', ]); $conversation->load('messages'); } return view('chat.index', [ 'conversation' => $conversation, ]); } public function store(Request $request, OpenAiChatService $openai): RedirectResponse { $data = $request->validate([ 'prompt' => ['required', 'string', 'max:1000'], ]); $dailyLimit = max(5, (int) config('services.openai.daily_message_limit', 40)); $todayCount = ChatMessage::query() ->where('role', 'user') ->whereDate('created_at', now()->toDateString()) ->whereHas('conversation', fn ($q) => $q->where('user_id', $request->user()->id)) ->count(); if ($todayCount >= $dailyLimit) { return redirect() ->route('chat.index') ->with('chat_error', "Batas harian chat ({$dailyLimit}) sudah tercapai. Coba lagi besok atau minta limit dinaikkan."); } $conversation = $request->user() ->chatConversations() ->latest() ->first(); if (! $conversation) { $conversation = $request->user()->chatConversations()->create([ 'title' => 'Chat AI', ]); } $conversation->messages()->create([ 'role' => 'user', 'content' => $data['prompt'], ]); $historyLimit = max(2, (int) config('services.openai.history_limit', 10)); $messages = $conversation->messages() ->latest('id') ->limit($historyLimit) ->get(['role', 'content']) ->reverse() ->map(fn ($message) => [ 'role' => $message->role, 'content' => $message->content, ]) ->values() ->all(); $systemPrompt = config('services.openai.system_prompt'); $languageGuard = 'Aturan wajib: selalu jawab dalam Bahasa Indonesia. Gunakan Bahasa Inggris hanya jika pengguna secara eksplisit memintanya.'; $finalSystemPrompt = trim((string) $systemPrompt); if ($finalSystemPrompt !== '') { $finalSystemPrompt .= "\n\n".$languageGuard; } else { $finalSystemPrompt = $languageGuard; } array_unshift($messages, [ 'role' => 'system', 'content' => $finalSystemPrompt, ]); try { $reply = $openai->reply($messages); } catch (\Throwable $e) { $conversation->messages()->create([ 'role' => 'assistant', 'content' => 'Maaf, AI belum bisa merespons sekarang. Cek konfigurasi OPENAI_API_KEY dan model OpenAI kamu.', ]); return redirect() ->route('chat.index') ->with('chat_error', $e->getMessage()); } $conversation->messages()->create([ 'role' => 'assistant', 'content' => $reply, ]); return redirect()->route('chat.index'); } }