Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ADVAPP-896]: Improve processing speed for chat in the Enterprise AI Assistant #1098

Merged
merged 38 commits into from
Nov 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
5119b93
Swap out the references to the actions directly for buttons
Orrison Oct 31, 2024
e4f0a7d
Add the icons in the folder view as ewll
Orrison Oct 31, 2024
1bfd6d4
swap out actions for folders as well
Orrison Oct 31, 2024
430df0a
Move the actions out of the loop
Orrison Nov 1, 2024
beebdb9
Load the chats without folders into alpine
Orrison Nov 4, 2024
9ad54df
Install Clockwork
Orrison Nov 4, 2024
339978b
Gitignore clockwork items
Orrison Nov 4, 2024
5845169
Clockwork config
Orrison Nov 4, 2024
65afde6
Start to move folders to Alpine
Orrison Nov 4, 2024
2e0cd7f
Finish moving all folder code to alpine
Orrison Nov 4, 2024
f354fde
Updated selected thread when creating a thread
Orrison Nov 4, 2024
353dd9d
Fix a couple of issues
Orrison Nov 5, 2024
05387de
More fixes
Orrison Nov 5, 2024
ca409a3
Remove blade if statement
Orrison Nov 5, 2024
2d98c2f
Modification of gitignore
Orrison Nov 5, 2024
7592d87
Call the $wire directive directly
Orrison Nov 5, 2024
06695f0
Bring back the loading indicator
Orrison Nov 5, 2024
aab0c99
Bring the loading indicator back to folder thread actions
Orrison Nov 5, 2024
00b402c
Add back loading indicator for threads without a folder
Orrison Nov 5, 2024
a12c6e4
Restore the loading indicator to folders
Orrison Nov 5, 2024
2331dab
Remove bad import
Orrison Nov 5, 2024
2738542
Fix updating the time on message send
Orrison Nov 5, 2024
d95f87e
Remove unneeded index
Orrison Nov 5, 2024
9c1a7f2
Fix last engaged at for folder threads
Orrison Nov 5, 2024
7ee3e7e
chore: fix enforcement of copyright on all files
Orrison Nov 5, 2024
bae97a5
Remove uneeded loading data
Orrison Nov 5, 2024
0f3701f
chore: fix code style
Orrison Nov 5, 2024
fb5c37c
disable clockwork by default
Orrison Nov 5, 2024
887875f
Fix formatting
Orrison Nov 5, 2024
e3a0004
Final tweaks
Orrison Nov 5, 2024
9013784
chore: fix code style
Orrison Nov 5, 2024
820c25e
Refactors
Orrison Nov 6, 2024
ad2a3ce
test
Orrison Nov 6, 2024
116e844
Revert test
Orrison Nov 6, 2024
50945e1
chore: fix code style
Orrison Nov 6, 2024
d10f633
Fix tests
Orrison Nov 6, 2024
aafa8fa
Remove pulling in the assistant
Orrison Nov 6, 2024
9ec30ac
Minor fixes
Orrison Nov 6, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions app-modules/ai/resources/js/chat.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ document.addEventListener('alpine:init', () => {
this.isIncomplete = false;
this.error = null;

this.$dispatch(`message-sent-${threadId}`);
this.$dispatch('message-sent', { threadId: threadId });

this.latestMessage = this.message;

Expand Down Expand Up @@ -235,7 +235,7 @@ document.addEventListener('alpine:init', () => {
this.isIncomplete = false;
this.error = null;

this.$dispatch(`message-sent-${threadId}`);
this.$dispatch('message-sent', { threadId: threadId });

this.$nextTick(async () => {
await this.handleMessageResponse({
Expand All @@ -261,7 +261,7 @@ document.addEventListener('alpine:init', () => {
this.isIncomplete = false;
this.error = null;

this.$dispatch(`message-sent-${threadId}`);
this.$dispatch('message-sent', { threadId: threadId });

this.$nextTick(async () => {
await this.handleMessageResponse({
Expand Down
60 changes: 59 additions & 1 deletion app-modules/ai/resources/js/chats.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@
</COPYRIGHT>
*/
document.addEventListener('alpine:init', () => {
Alpine.data('chats', () => ({
Alpine.data('chats', ($wire) => ({
loading: {
type: null,
identifier: null,
},
threadId: null,
startFolder: null,
dragging: false,
Expand Down Expand Up @@ -91,5 +95,59 @@ document.addEventListener('alpine:init', () => {
expanded(folderId) {
return this.expandedFolder === folderId;
},
async selectThread(thread) {
this.loading.type = 'thread';
this.loading.identifier = thread.id;

await $wire.selectThread(thread);

this.loading.type = null;
this.loading.identifier = null;
},
async moveThread(threadId) {
this.loading.type = 'moveThreadAction';
this.loading.identifier = threadId;

await $wire.mountAction('moveThread', { thread: threadId });

this.loading.type = null;
this.loading.identifier = null;
},
async editThread(threadId) {
this.loading.type = 'editThreadAction';
this.loading.identifier = threadId;

await $wire.mountAction('editThread', { thread: threadId });

this.loading.type = null;
this.loading.identifier = null;
},
async deleteThread(threadId) {
this.loading.type = 'deleteThreadAction';
this.loading.identifier = threadId;

await $wire.mountAction('deleteThread', { thread: threadId });

this.loading.type = null;
this.loading.identifier = null;
},
async renameFolder(folderId) {
this.loading.type = 'renameFolderAction';
this.loading.identifier = folderId;

await $wire.mountAction('renameFolder', { folder: folderId });

this.loading.type = null;
this.loading.identifier = null;
},
async deleteFolder(folderId) {
this.loading.type = 'deleteFolderAction';
this.loading.identifier = folderId;

await $wire.mountAction('deleteFolder', { folder: folderId });

this.loading.type = null;
this.loading.identifier = null;
},
}));
});
395 changes: 279 additions & 116 deletions app-modules/ai/resources/views/components/assistant.blade.php

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,10 @@
namespace AdvisingApp\Ai\Filament\Pages\Assistant\Concerns;

use Exception;
use App\Models\User;
use Filament\Actions\Action;
use Livewire\Attributes\Locked;
use Illuminate\Http\JsonResponse;
use Livewire\Attributes\Computed;
use Filament\Actions\StaticAction;
use AdvisingApp\Ai\Models\AiThread;
use Filament\Forms\Components\Select;
Expand All @@ -49,14 +50,23 @@
use AdvisingApp\Ai\Models\AiThreadFolder;
use Symfony\Component\HttpFoundation\Response;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;

trait CanManageFolders
{
#[Computed]
public function folders(): EloquentCollection
#[Locked]
public array $folders = [];

public function mountCanManageFolders(): void
{
return auth()->user()
$this->folders = $this->getFolders();
}

public function getFolders(): array
{
/** @var User $user */
$user = auth()->user();

return $user
->aiThreadFolders()
->where('application', static::APPLICATION)
->with([
Expand All @@ -65,7 +75,8 @@ public function folders(): EloquentCollection
->withMax('messages', 'created_at'),
])
->orderBy('name')
->get();
->get()
->toArray();
}

public function newFolderAction(): Action
Expand Down Expand Up @@ -126,7 +137,7 @@ public function renameFolderAction(): Action
->find($arguments['folder'])
?->update(['name' => $data['name']]);

unset($this->folders);
$this->folders = $this->getFolders();
})
->icon('heroicon-m-pencil')
->color('warning')
Expand All @@ -149,7 +160,7 @@ public function deleteFolderAction(): Action
->find($arguments['folder'])
?->delete();

unset($this->folders);
$this->folders = $this->getFolders();
})
->icon('heroicon-m-trash')
->color('danger')
Expand Down Expand Up @@ -257,6 +268,7 @@ protected function moveThread(AiThread $thread, ?AiThreadFolder $folder): void
->save();
}

unset($this->threadsWithoutAFolder, $this->folders);
$this->threadsWithoutAFolder = $this->getThreadsWithoutAFolder();
$this->folders = $this->getFolders();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,9 @@
use AdvisingApp\Report\Jobs\RecordTrackedEvent;
use AdvisingApp\Ai\Jobs\PrepareAiThreadEmailing;
use AdvisingApp\Ai\Services\Contracts\AiServiceLifecycleHooks;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;

/**
* @property-read array $customAssistants
* @property-read EloquentCollection $threadsWithoutAFolder
*/
trait CanManageThreads
{
Expand All @@ -78,6 +76,14 @@ trait CanManageThreads

public $assistantSwitcherMobile = null;

#[Locked]
public array $threadsWithoutAFolder = [];

public function mountCanManageThreads(): void
{
$this->threadsWithoutAFolder = $this->getThreadsWithoutAFolder();
}

#[Computed]
public function customAssistants(): array
{
Expand Down Expand Up @@ -171,23 +177,26 @@ public function createThread(?AiAssistant $assistant = null): void
$this->thread = app(CreateThread::class)(static::APPLICATION, $assistant);
}

#[Computed]
public function threadsWithoutAFolder(): EloquentCollection
public function getThreadsWithoutAFolder(): array
{
return auth()->user()
/** @var User $user */
$user = auth()->user();

return $user
->aiThreads()
->withMax('messages', 'created_at')
->whereRelation('assistant', 'application', static::APPLICATION)
->whereNotNull('name')
->doesntHave('folder')
->latest('updated_at')
->with('assistant')
->get();
->get()
->each->append('last_engaged_at')
->toArray();
}

public function loadFirstThread(): void
{
$this->selectThread($this->threadsWithoutAFolder->whereNull('assistant.archived_at')->first());
$this->selectThread(collect($this->threadsWithoutAFolder)->whereNull('assistant.archived_at')->first());

if ($this->thread) {
$service = $this->thread->assistant->model->getService();
Expand All @@ -202,12 +211,14 @@ public function loadFirstThread(): void
$this->createThread();
}

public function selectThread(?AiThread $thread): void
public function selectThread(?array $thread): void
{
if (! $thread) {
return;
}

$thread = AiThread::find($thread['id']);

if (
$this->thread &&
blank($this->thread->name) &&
Expand Down Expand Up @@ -264,13 +275,13 @@ public function saveThreadAction(): Action
->find($data['folder']);

if (! $folder) {
unset($this->threadsWithoutAFolder);
$this->threadsWithoutAFolder = $this->getThreadsWithoutAFolder();

return;
}

$this->moveThread($this->thread, $folder);
unset($this->folders);
$this->folders = $this->getFolders();
});
}

Expand All @@ -294,7 +305,8 @@ public function deleteThreadAction(): Action
$this->createThread();
}

unset($this->threadsWithoutAFolder, $this->folders);
$this->threadsWithoutAFolder = $this->getThreadsWithoutAFolder();
$this->folders = $this->getFolders();
})
->icon('heroicon-m-trash')
->color('danger')
Expand Down Expand Up @@ -335,7 +347,8 @@ public function editThreadAction(): Action
$thread->name = $data['name'];
$thread->save();

unset($this->threadsWithoutAFolder, $this->folders);
$this->threadsWithoutAFolder = $this->getThreadsWithoutAFolder();
$this->folders = $this->getFolders();
})
->icon('heroicon-m-pencil')
->color('warning')
Expand Down
16 changes: 15 additions & 1 deletion app-modules/ai/src/Models/AiThread.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@

use Carbon\Carbon;
use App\Models\User;
use Livewire\Wireable;
use App\Models\BaseModel;
use Carbon\CarbonInterface;
use App\Settings\DisplaySettings;
Expand All @@ -55,7 +56,7 @@
/**
* @mixin IdeHelperAiThread
*/
class AiThread extends BaseModel
class AiThread extends BaseModel implements Wireable
{
use CanAddAssistantLicenseGlobalScope;
use SoftDeletes;
Expand Down Expand Up @@ -117,6 +118,19 @@ public function prunable(): Builder
->whereDoesntHave('messages', fn (Builder $query) => $query->withTrashed());
}

public function toLivewire()
{
return [
'id' => $this->getKey(),
'name' => $this->name,
];
}

public static function fromLivewire($value)
{
return AiThread::query()->find($value['id']);
}

protected function lastEngagedAt(): Attribute
{
return Attribute::make(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@
]);

Livewire::test(PersonalAssistant::class)
->call('selectThread', $thread)
->call('selectThread', $thread->toArray())
->callAction('saveThread', [
'name' => $name = Str::random(),
])
Expand Down Expand Up @@ -274,7 +274,7 @@
]);

Livewire::test(PersonalAssistant::class)
->call('selectThread', $thread)
->call('selectThread', $thread->toArray())
->callAction('saveThread', [
'name' => $name = Str::random(),
'folder' => $folder->getKey(),
Expand Down Expand Up @@ -319,7 +319,7 @@
Livewire::test(PersonalAssistant::class)
->call('loadFirstThread')
->assertSet('thread.id', $thread->id)
->call('selectThread', $newThread)
->call('selectThread', $newThread->toArray())
->assertSet('thread.id', $newThread->id);
});

Expand All @@ -338,7 +338,7 @@
Livewire::test(PersonalAssistant::class)
->call('loadFirstThread')
->assertSet('thread.id', $thread->id)
->call('selectThread', $newThread)
->call('selectThread', $newThread->toArray())
->assertNotFound();
});

Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
"google/apiclient": "^2.17",
"guzzlehttp/guzzle": "^7.2",
"internachi/modular": "^2.2",
"itsgoingd/clockwork": "^5.2",
"kirschbaum-development/eloquent-power-joins": "^3.5",
"laravel/framework": "^10.48",
"laravel/octane": "^2.5",
Expand Down
Loading