messages = $this->chatable->chats()->orderByRaw('created_at, id')->limit(25)->get(['role', 'content'])->toArray(); } public function startCompletion($suggestedPrompt = null) { // prevent spam if ($this->isRateLimited() || $this->streaming) { array_push($this->messages, [ 'role' => 'assistant', 'content' => __('Hang on! You\'re doing that too much.') ]); $this->js('scrollChatWindow(250)'); return; } if ($suggestedPrompt) { $this->prompt = $suggestedPrompt; } if (empty(trim($this->prompt))) { $this->resetPrompt(); array_push($this->messages, ['role' => 'assistant', 'content' => __('Feel free to ask me a question!')]); $this->js('scrollChatWindow(250)'); return; } $this->chatable->chats()->save(new AiChat(['role' => 'user', 'content' => $this->prompt])); array_push($this->messages, ['role' => 'user', 'content' => $this->prompt]); $this->js('scrollChatWindow(250)'); $this->resetPrompt(); $this->streaming = true; $this->js('$wire.generate()'); } public function generate(): void { try { $stream = OpenAI::chat()->createStreamed([ 'model' => config('openai.model'), 'messages' => [ ['role' => 'system', 'content' => $this->system_prompt], ...array_slice($this->messages, -10) ], ]); } catch (\Exception $e) { $this->chatable->chats()->save(new AiChat(['role' => 'assistant', 'content' => $e->getMessage()])); array_push($this->messages, ['role' => 'assistant', 'content' => $e->getMessage()]); $this->resetPrompt(); return; } $this->stream(to: "answer", content: '', replace: true); foreach($stream as $response){ if(!empty($response->choices[0]->delta->content)) { $this->stream(to: 'answer', content: $response->choices[0]->delta->content, replace: false); $this->answer .= $response->choices[0]->delta->content; } $this->js('scrollChatWindow()'); } $this->chatable->chats()->save(new AiChat(['role' => 'assistant', 'content' => $this->answer])); array_push($this->messages, ['role' => 'assistant', 'content' => $this->answer]); $this->resetPrompt(); } public function resetPrompt(): void { $this->answer = null; $this->prompt = null; $this->streaming = false; } public function isRateLimited(): bool { $rateLimitKey = auth()->id() . '/' . $this->chatable->id; if (RateLimiter::tooManyAttempts($rateLimitKey, 20)) { return true; } RateLimiter::hit($rateLimitKey, 60); return false; } }; ?>
{{-- close button --}} {{-- chat window --}}

AI {{ __('Hi, how can I help?') }}

@foreach($messages as $message) @if ($message['role'] == 'user')

{{ __('You') }} {{ $message['content'] }}

@else
AI {!! Str::markdown($message['content']) !!}
@endif @endforeach @if($streaming)

AI {{ $answer }}

@endif
{{-- prompt input --}}
@foreach($suggested_prompts as $prompt) @endforeach

{{ __('Advice generated by AI may contain errors. Use at your own risk. Always consult a licensed investment advisor.') }}