diff --git a/resources/css/app.css b/resources/css/app.css index fb8bafd..1189590 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -6,15 +6,33 @@ display: none; } -.ai-chat ul { +.ai-chat ul, .ai-chat ol, .ai-chat ol li > ul { margin-left: 1.1rem; } -.ai-chat ul li { +.ai-chat ul > li { padding-left: 1.1rem; list-style-type: disc; } +.ai-chat ol > li { + padding-left: 1.1rem; + list-style-type: decimal; +} + +.ai-chat ol li li { + padding-left: 0rem; + list-style-type: none; +} + +.ai-chat ol li li::before { + content: " - "; +} + .ai-chat li, .ai-chat p { - padding-bottom: .25em; + padding-bottom: .25rem; +} + +.ai-chat code { + font-size: .75rem; } \ No newline at end of file diff --git a/resources/views/livewire/ai-chat-window.blade.php b/resources/views/livewire/ai-chat-window.blade.php index 8fc8d70..a5f59bc 100644 --- a/resources/views/livewire/ai-chat-window.blade.php +++ b/resources/views/livewire/ai-chat-window.blade.php @@ -60,17 +60,19 @@ new class extends Component { $this->resetPrompt(); $this->streaming = true; - $this->js('$wire.generate()'); + $this->js('$wire.generateCompletion()'); } - public function generate(): void + public function generateCompletion(): void { try { $stream = OpenAI::chat()->createStreamed([ 'model' => config('openai.model'), 'messages' => [ - ['role' => 'system', 'content' => $this->system_prompt], + ['role' => 'system', 'content' => "Today's date is " + .now()->format('Y-m-d') + .".\n\n".$this->system_prompt], ...array_slice($this->messages, -10) ], ]); @@ -96,6 +98,76 @@ new class extends Component { $this->chatable->chats()->save(new AiChat(['role' => 'assistant', 'content' => $this->answer])); array_push($this->messages, ['role' => 'assistant', 'content' => $this->answer]); $this->resetPrompt(); + $this->js('$wire.generateSuggestedPrompts()'); + } + + public function generateSuggestedPrompts(): void + { + try { + $suggested_prompts = OpenAI::chat()->create([ + 'model' => config('openai.model'), + 'response_format' => [ + 'type' => 'json_schema', + 'json_schema' => [ + 'name' => 'suggested_prompts_schema', + 'strict' => true, + 'schema' => [ + "type" => "object", + "properties" => [ + "suggested_prompts" => [ + "type" => "array", + "items" => [ + "type" => "object", + "properties" => [ + "text" => [ + "type" => "string", + "description" => "The prompt question (no more than 5 words)" + ], + "value" => [ + "type" => "string", + "description" => "The detailed version of the question" + ] + ], + "required" => ["text", "value"], + "additionalProperties" => false + ] + ] + ], + "required" => ["suggested_prompts"], + "additionalProperties" => false + ] + ] + ], + 'messages' => [ + ['role' => 'system', 'content' => " + Your role is to assist investors in asking thoughtful questions to their investment advisors. + + When you help investors ask good questions, you should ensure the questions are based on the + provided context. Be sure to keep the questions short! + + The questions you recommend might be based on natural follow up from the given context, requests + to clarify undefined terms, common decision frameworks, possible risks or benefits, or commonly + understood investing concepts. + + Your response should only include valid JSON. + "], + ['role' => 'user', 'content' => " + Generate a list of ". rand(1,5) ." follow up questions a savvy investor might ask their advisor + based on the following conversation: + \n\n + ".json_encode(array_slice($this->messages, -4)) + ], + ], + ]); + + $this->suggested_prompts = json_decode($suggested_prompts->choices[0]->message->content, true)['suggested_prompts']; + + } catch (\Exception $e) { + + $this->suggested_prompts = []; + $this->error($e->getMessage()); + return; + } } public function resetPrompt(): void @@ -132,41 +204,53 @@ new class extends Component { }); } }" - class="flex flex-col" + class="fixed z-50 bottom-8 right-8" > + {{-- toggle button --}} - + + {{-- popup --}}
- - - {{-- close button --}} - +
+
+

{{ __('AI Chat') }}

+ +
{{-- chat window --}} -
+
-
- @foreach($suggested_prompts as $prompt) - - @endforeach - -
- -
- -
+
+
+
+ @foreach($suggested_prompts as $prompt) + {{ $prompt['text'] }} + @endforeach -
- - -
-
-

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

-
- - +
+ +
+ + +
+ + +
+ +
+

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

+
+ +
+