Merge pull request #5 from investbrainapp/dev

feat:improved LLM follow up questions prompt (and more)
This commit is contained in:
hackerESQ
2024-11-06 20:53:28 -06:00
committed by GitHub
8 changed files with 48 additions and 121 deletions
+1
View File
@@ -1,3 +1,4 @@
/packages
/.phpunit.cache
/node_modules
/public/build
+1
View File
@@ -32,6 +32,7 @@ class User extends Authenticatable implements MustVerifyEmail
];
protected $hidden = [
'admin',
'password',
'remember_token',
'two_factor_recovery_codes',
@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->boolean('admin')->nullable()->after('profile_photo_path');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('admin');
});
}
};
@@ -121,7 +121,7 @@ new class extends Component {
"properties" => [
"text" => [
"type" => "string",
"description" => "The prompt question (no more than 5 words)"
"description" => "The suggested prompt question (no more than 5 words)"
],
"value" => [
"type" => "string",
@@ -140,20 +140,21 @@ new class extends Component {
],
'messages' => [
['role' => 'system', 'content' => "
Your role is to assist investors in asking thoughtful questions to their investment advisors.
Your role is to assist investors in asking thoughtful questions of 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!
When you help investors ask good questions, you should ensure the you questions you recommend
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.
to further refine a previous response, clarify undefined terms, common decision frameworks,
possible risks or benefits, or commonly understood investing concepts that may require additional
explanation.
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:
Generate between 1 and 5 (no more than 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))
],
@@ -366,7 +367,7 @@ new class extends Component {
</div>
<div class="w-full mt-2">
<p class="text-xs text-secondary leading-tight">{{ __('Advice generateCompletiond by AI may contain errors. Use at your own risk. Always consult a licensed investment advisor.') }} </p>
<p class="text-xs text-secondary leading-tight">{{ __('Advice generated by AI may contain errors. Use at your own risk. Always consult a licensed investment advisor.') }} </p>
</div>
</form>
</div>
@@ -5,9 +5,11 @@ use Illuminate\Support\Collection;
use Livewire\Attributes\Rule;
use Livewire\Volt\Component;
use Mary\Traits\Toast;
use App\Traits\WithTrimStrings;
new class extends Component {
use Toast;
use WithTrimStrings;
// props
public ?Portfolio $portfolio;
@@ -9,9 +9,11 @@ use Livewire\Attributes\{Computed};
use Livewire\Volt\Component;
use Mary\Traits\Toast;
use Illuminate\Validation\Rule;
use App\Traits\WithTrimStrings;
new class extends Component {
use Toast;
use WithTrimStrings;
// props
public ?Portfolio $portfolio;
-105
View File
@@ -1,105 +0,0 @@
@extends('layouts.main-layout', ['attributes' => null])
@section('body')
<div class="flex flex-col min-h-[100dvh] bg-gradient-to-br from-[#03255B] to-[#011638] text-white">
<header class="px-4 lg:px-6 h-14 flex justify-between items-center ">
<div class="w-10">
<x-glyph-only-logo class="text-white" />
</div>
@auth
<a href="{{ route('dashboard') }}">Dashboard</a>
@endauth
</header>
<main class="flex-1 flex flex-col items-center justify-center px-4 md:px-6 gap-8">
<div class="text-center space-y-4">
<h1 class="text-4xl sm:text-5xl md:text-6xl font-bold tracking-tighter">A better portfolio</h1>
<div class="flex justify-center items-center gap-4" title="Yeah, that's halloween.">
<div class="bg-white/10 px-4 py-2 rounded-lg text-2xl font-bold" x-data="countdown"
x-init="startCountdown" id="countdown">
<span x-text="days"></span>d
<span x-text="hours"></span>h
<span x-text="minutes"></span>m
<span x-text="seconds"></span>s
</div>
</div>
</div>
<div class="max-w-lg space-y-4">
<p class="text-md text-center">
Investbrain is a smart open-source platform that consolidates your portfolios from different brokerages,
tracks market performance across your portfolios, and gives you an AI-powered investment best friend.
</p>
<div class="flex flex-col items-center gap-2 pt-7">
<p class="text-lg font-medium">Stay up to date on our progress!</p>
<form class="flex gap-2 w-full"
action="https://mail.lumifylabs.com/subscribe/0dcb1b4e-8a73-46f6-b9b5-6a6c12ef2f73" method="post">
<input
class="flex rounded-md px-3 py-2 text-md ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed flex-1 bg-white/10 text-white placeholder:text-white/50"
placeholder="steve@savvyinvestor.com" name="email" type="email" />
<div style="position: absolute; left: -9999px">
<label for="website-robot">Your Website</label>
<input type="text" id="website-robot" name="robot" tabindex="-1" autocomplete="nope" />
</div>
<input type="hidden" name="tags" value="coming-soon-page" />
<button
class="rounded-md text-md font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-primary text-primary-foreground hover:bg-primary/90 h-10 px-4 py-2"
type="submit">
Join Waitlist
</button>
</form>
</div>
<div class="flex flex-col items-center gap-2 pt-7">
<a target="_blank" href="https://github.com/investbrainapp/investbrain" title="We're open source!" class="">
<x-github-icon />
</a>
</div>
</div>
</main>
<footer
class="flex flex-col gap-2 sm:flex-row py-6 w-full shrink-0 items-center px-4 md:px-6 border-t border-white/20">
<p class="text-xs text-white/50">© {{ date('Y') }} Investbrain. All rights reserved.</p>
<nav class="sm:ml-auto flex gap-4 sm:gap-6">
<a class="text-xs hover:underline underline-offset-4 text-white/50" href="{{ route('terms.show') }}">
Terms
</a>
<a class="text-xs hover:underline underline-offset-4 text-white/50" href="{{ route('policy.show') }}">
Privacy
</a>
</nav>
</footer>
</div>
<script>
function countdown() {
return {
days: 0,
hours: 0,
minutes: 0,
seconds: 0,
countdownDate: new Date("Oct 31, 2024 00:00:00").getTime(),
startCountdown() {
this.updateCountdown();
setInterval(() => this.updateCountdown(), 1000);
},
updateCountdown() {
const now = new Date().getTime();
const distance = this.countdownDate - now;
if (distance < 0) {
clearInterval();
document.getElementById("countdown").innerText = "Coming Soon!";
return;
}
this.days = Math.floor(distance / (1000 * 60 * 60 * 24));
this.hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
this.minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
this.seconds = Math.floor((distance % (1000 * 60)) / 1000);
}
};
}
</script>
@endsection
+4 -7
View File
@@ -1,5 +1,6 @@
<?php
use Illuminate\Support\Facades\View;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\HoldingController;
use App\Http\Controllers\DashboardController;
@@ -11,16 +12,12 @@ use Laravel\Jetstream\Http\Controllers\Livewire\PrivacyPolicyController;
use Laravel\Jetstream\Http\Controllers\Livewire\TermsOfServiceController;
Route::get('/', function () {
if (config('investbrain.self_hosted', true)) {
if (config('investbrain.self_hosted', false) && View::exists('landing-page::index')) {
return redirect(route('dashboard'));
return view('landing-page::index');
}
return view('welcome');
});
Route::get('/test', function () {
//
return redirect(route('dashboard'));
});
Route::middleware(['auth:sanctum', config('jetstream.auth_session')])->group(function () {