File size: 3,655 Bytes
1501522
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
<?php

namespace App\Http\Controllers;

use App\Models\ChatMessage;
use App\Services\OpenAiChatService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class ChatController extends Controller
{
    public function index(Request $request): View
    {
        $conversation = $request->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');
    }
}