├── .editorconfig ├── .env.example ├── .gitattributes ├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── app ├── Console │ └── Kernel.php ├── Exceptions │ └── Handler.php ├── Http │ ├── Controllers │ │ ├── Controller.php │ │ ├── FileController.php │ │ ├── FileEditorController.php │ │ ├── LibraryController.php │ │ └── PlaygroundController.php │ ├── Kernel.php │ ├── Middleware │ │ ├── Authenticate.php │ │ ├── EncryptCookies.php │ │ ├── PreventRequestsDuringMaintenance.php │ │ ├── RedirectIfAuthenticated.php │ │ ├── TrimStrings.php │ │ ├── TrustHosts.php │ │ ├── TrustProxies.php │ │ ├── ValidateSignature.php │ │ └── VerifyCsrfToken.php │ └── Requests │ │ ├── ChunkUpdateRequest.php │ │ ├── FileUploadRequest.php │ │ ├── LibrarySaveRequest.php │ │ └── PlaygroundSendRequest.php ├── Models │ ├── Library.php │ ├── LibraryFile.php │ ├── LibraryFileChunkAttachment.php │ ├── Provider.php │ ├── ProviderModel.php │ └── User.php ├── Providers │ ├── AppServiceProvider.php │ ├── AuthServiceProvider.php │ ├── BroadcastServiceProvider.php │ ├── EventServiceProvider.php │ └── RouteServiceProvider.php └── Services │ ├── Ai │ ├── AiService.php │ ├── Chat │ │ ├── AiChat.php │ │ ├── NullAiChat.php │ │ └── OpenAiChat.php │ ├── Completions │ │ ├── AiCompletion.php │ │ ├── NullAiCompletion.php │ │ └── OpenAiCompletion.php │ ├── Embeddings │ │ ├── AiEmbedding.php │ │ ├── NullAiEmbedding.php │ │ └── OpenAiEmbedding.php │ └── Models │ │ ├── AiModel.php │ │ ├── AiModelResolver.php │ │ ├── BaseAiModel.php │ │ ├── Gpt35Turbo16KAiModel.php │ │ ├── Gpt35TurboAiModel.php │ │ ├── Gpt4AiModel.php │ │ ├── NullAiModel.php │ │ ├── TextAda001AiModel.php │ │ ├── TextBabbage001AiModel.php │ │ ├── TextCuris001AiModel.php │ │ ├── TextDavinci002AiModel.php │ │ └── TextDavinci003AiModel.php │ ├── Converters │ ├── ConverterResolver.php │ └── Handlers │ │ ├── BaseConverterHandler.php │ │ ├── ConverterHandler.php │ │ ├── CsvConverterHandler.php │ │ ├── PdfConverterHandler.php │ │ └── TextConverterHandler.php │ ├── Editors │ ├── BaseFileChunks.php │ ├── FileChunksEditor.php │ ├── FileChunksEmbeddedEditor.php │ └── Filters │ │ ├── Chains │ │ ├── ChunkEditorFilterChain.php │ │ ├── EditorFilterChain.php │ │ ├── EmbeddingEditorFilterChain.php │ │ ├── PlaygroundEditorFilterChain.php │ │ └── PlaygroundSendFilterChain.php │ │ ├── EditorFilter.php │ │ ├── LowerCaseEditorFilter.php │ │ ├── StopWordEditorFilter.php │ │ ├── StripPunctEditorFilter.php │ │ ├── StripSpecialEditorFilter.php │ │ └── StripTagEditorFilter.php │ └── Storage │ ├── Adapters │ ├── EmbeddedStepService.php │ ├── StorageStepService.php │ └── UploadedStepService.php │ ├── Drivers │ ├── LocalStorageDriver.php │ └── StorageDriver.php │ ├── Events │ ├── BaseCopyStorageEvent.php │ ├── BaseDeleteStorageEvent.php │ ├── BaseDownloadStorageEvent.php │ ├── BaseExistsStorageEvent.php │ ├── BaseGetStorageEvent.php │ ├── BasePathStorageEvent.php │ ├── BaseUploadStorageEvent.php │ ├── BaseUploadStreamStorageEvent.php │ ├── Copy │ │ ├── CopyEmbeddedStorageEvent.php │ │ └── CopyRawStorageEvent.php │ ├── Delete │ │ ├── DeleteEmbeddedStorageEvent.php │ │ └── DeleteRawStorageEvent.php │ ├── Download │ │ ├── DownloadEmbeddedStorageEvent.php │ │ └── DownloadRawStorageEvent.php │ ├── Exists │ │ ├── ExistsEmbeddedStorageEvent.php │ │ └── ExistsRawStorageEvent.php │ ├── Get │ │ ├── GetEmbeddedStorageEvent.php │ │ └── GetRawStorageEvent.php │ ├── Path │ │ ├── PathEmbeddedStorageEvent.php │ │ └── PathRawStorageEvent.php │ ├── StorageEvent.php │ ├── Upload │ │ ├── UploadEmbeddedStorageEvent.php │ │ └── UploadRawStorageEvent.php │ ├── UploadStream │ │ ├── UploadStreamEmbeddedStorageEvent.php │ │ └── UploadStreamRawStorageEvent.php │ └── Url │ │ ├── UrlEmbeddedStorageEvent.php │ │ └── UrlRawStorageEvent.php │ └── Handlers │ ├── BaseCopyStorageHandler.php │ ├── BaseDeleteStorageHandler.php │ ├── BaseDownloadStorageHandler.php │ ├── BaseExistsStorageHandler.php │ ├── BaseGetStorageHandler.php │ ├── BasePathStorageHandler.php │ ├── BaseUploadStorageHandler.php │ ├── BaseUploadStreamStorageHandler.php │ ├── BaseUrlStorageHandler.php │ ├── Copy │ ├── CopyEmbeddedLocalStorageHandler.php │ └── CopyRawLocalStorageHandler.php │ ├── Delete │ ├── DeleteEmbeddedLocalStorageHandler.php │ └── DeleteRawLocalStorageHandler.php │ ├── Download │ ├── DownloadEmbeddedLocalStorageHandler.php │ └── DownloadRawLocalStorageHandler.php │ ├── Exists │ ├── ExistsEmbeddedLocalStorageHandler.php │ └── ExistsRawLocalStorageHandler.php │ ├── Get │ ├── GetEmbeddedLocalStorageHandler.php │ └── GetRawLocalStorageHandler.php │ ├── Path │ ├── PathEmbeddedLocalStorageHandler.php │ └── PathRawLocalStorageHandler.php │ ├── StorageHandler.php │ ├── Upload │ ├── UploadEmbeddedLocalStorageHandler.php │ └── UploadRawLocalStorageHandler.php │ ├── UploadStream │ ├── UploadStreamEmbeddedLocalStorageHandler.php │ └── UploadStreamRawLocalStorageHandler.php │ └── Url │ ├── UrlEmbeddedLocalStorageHandler.php │ └── UrlRawLocalStorageHandler.php ├── artisan ├── bootstrap ├── app.php └── cache │ └── .gitignore ├── composer.json ├── composer.lock ├── composer.phar ├── config ├── app.php ├── auth.php ├── broadcasting.php ├── cache.php ├── cors.php ├── database.php ├── filesystems.php ├── hashing.php ├── logging.php ├── mail.php ├── queue.php ├── sanctum.php ├── services.php ├── session.php └── view.php ├── database ├── .gitignore ├── factories │ └── UserFactory.php ├── migrations │ ├── 2014_10_12_000000_create_users_table.php │ ├── 2014_10_12_100000_create_password_reset_tokens_table.php │ ├── 2019_08_19_000000_create_failed_jobs_table.php │ ├── 2019_12_14_000001_create_personal_access_tokens_table.php │ ├── 2023_05_19_180101_create_libraries_table.php │ ├── 2023_05_20_081521_create_library_files_table.php │ ├── 2023_05_20_184919_add_chunk_separator_to_libraries_table.php │ ├── 2023_05_20_185027_add_chunked_list_library_file_table.php │ ├── 2023_05_20_194118_add_embedded_model_into_library.php │ ├── 2023_05_21_083644_create_providers_table.php │ ├── 2023_05_21_084107_create_provider_models_table.php │ ├── 2023_05_22_123515_add_optional_fields_into_library_files.php │ ├── 2023_05_22_154003_add_strip_fields_to_library_files.php │ ├── 2023_05_23_095012_add_count_words_into_files.php │ └── 2023_11_04_150205_add_g_p_t3516_k_model_into_models.php └── seeders │ ├── DatabaseSeeder.php │ ├── LibrarySeeder.php │ ├── ProviderModelSeeder.php │ └── ProviderSeeder.php ├── docker-compose.yml ├── docker ├── nginx │ └── embedditor.conf └── startup.sh ├── phpunit.xml ├── public ├── .htaccess ├── css │ ├── bootstrap.min.css │ └── bootstrap.min.css.map ├── favicon.ico ├── images │ ├── android-icon-144x144.png │ ├── android-icon-192x192.png │ ├── android-icon-36x36.png │ ├── android-icon-48x48.png │ ├── android-icon-72x72.png │ ├── android-icon-96x96.png │ ├── apple-icon-114x114.png │ ├── apple-icon-120x120.png │ ├── apple-icon-144x144.png │ ├── apple-icon-152x152.png │ ├── apple-icon-180x180.png │ ├── apple-icon-57x57.png │ ├── apple-icon-60x60.png │ ├── apple-icon-72x72.png │ ├── apple-icon-76x76.png │ ├── apple-icon-precomposed.png │ ├── apple-icon.png │ ├── browserconfig.xml │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon-96x96.png │ ├── favicon.ico │ ├── logo.jpg │ ├── manifest.json │ ├── ms-icon-144x144.png │ ├── ms-icon-150x150.png │ ├── ms-icon-310x310.png │ └── ms-icon-70x70.png ├── index.php ├── js │ ├── bootstrap.min.js │ ├── bootstrap.min.js.map │ └── jquery-3.7.0.min.js └── robots.txt ├── resources └── views │ ├── file │ └── chunks │ │ └── edit.blade.php │ ├── layouts │ └── app.blade.php │ ├── library │ └── index.blade.php │ └── playground │ └── index.blade.php ├── routes ├── api.php ├── channels.php ├── console.php └── web.php ├── storage ├── app │ ├── .gitignore │ └── public │ │ └── .gitignore ├── framework │ ├── .gitignore │ ├── cache │ │ ├── .gitignore │ │ └── data │ │ │ └── .gitignore │ ├── sessions │ │ └── .gitignore │ ├── testing │ │ └── .gitignore │ └── views │ │ └── .gitignore └── logs │ └── .gitignore └── tests ├── CreatesApplication.php ├── Feature └── ExampleTest.php ├── TestCase.php └── Unit └── ExampleTest.php /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 4 7 | indent_style = space 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | 14 | [*.{yml,yaml}] 15 | indent_size = 2 16 | 17 | [docker-compose.yml] 18 | indent_size = 4 19 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | APP_NAME=Embedditor 2 | APP_ENV=local 3 | APP_KEY= 4 | APP_DEBUG=true 5 | APP_URL=http://localhost 6 | 7 | LOG_CHANNEL=stack 8 | LOG_DEPRECATIONS_CHANNEL=null 9 | LOG_LEVEL=debug 10 | 11 | DB_CONNECTION=mysql 12 | DB_HOST=127.0.0.1 13 | DB_PORT=3306 14 | DB_DATABASE=laravel 15 | DB_USERNAME=root 16 | DB_PASSWORD= 17 | 18 | BROADCAST_DRIVER=log 19 | CACHE_DRIVER=file 20 | FILESYSTEM_DISK=local 21 | QUEUE_CONNECTION=sync 22 | SESSION_DRIVER=file 23 | SESSION_LIFETIME=120 24 | 25 | OPENAI_API_KEY= 26 | 27 | MEMCACHED_HOST=127.0.0.1 28 | 29 | REDIS_HOST=127.0.0.1 30 | REDIS_PASSWORD=null 31 | REDIS_PORT=6379 32 | 33 | MAIL_MAILER=smtp 34 | MAIL_HOST=mailpit 35 | MAIL_PORT=1025 36 | MAIL_USERNAME=null 37 | MAIL_PASSWORD=null 38 | MAIL_ENCRYPTION=null 39 | MAIL_FROM_ADDRESS="hello@example.com" 40 | MAIL_FROM_NAME="${APP_NAME}" 41 | 42 | AWS_ACCESS_KEY_ID= 43 | AWS_SECRET_ACCESS_KEY= 44 | AWS_DEFAULT_REGION=us-east-1 45 | AWS_BUCKET= 46 | AWS_USE_PATH_STYLE_ENDPOINT=false 47 | 48 | PUSHER_APP_ID= 49 | PUSHER_APP_KEY= 50 | PUSHER_APP_SECRET= 51 | PUSHER_HOST= 52 | PUSHER_PORT=443 53 | PUSHER_SCHEME=https 54 | PUSHER_APP_CLUSTER=mt1 55 | 56 | VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}" 57 | VITE_PUSHER_HOST="${PUSHER_HOST}" 58 | VITE_PUSHER_PORT="${PUSHER_PORT}" 59 | VITE_PUSHER_SCHEME="${PUSHER_SCHEME}" 60 | VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" 61 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | 3 | *.blade.php diff=html 4 | *.css diff=css 5 | *.html diff=html 6 | *.md diff=markdown 7 | *.php diff=php 8 | 9 | /.github export-ignore 10 | CHANGELOG.md export-ignore 11 | .styleci.yml export-ignore 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.phpunit.cache 2 | /node_modules 3 | /public/build 4 | /public/hot 5 | /public/storage 6 | /storage/*.key 7 | /vendor 8 | .env 9 | .env.backup 10 | .env.production 11 | .phpunit.result.cache 12 | Homestead.json 13 | Homestead.yaml 14 | auth.json 15 | npm-debug.log 16 | yarn-error.log 17 | /.fleet 18 | /.idea 19 | /.vscode 20 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Development php image 2 | FROM php:8.2-fpm AS PHP_DEV 3 | 4 | LABEL core=php 5 | 6 | # Add docker php ext repo 7 | ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/ 8 | 9 | # Install php extensions 10 | RUN chmod +x /usr/local/bin/install-php-extensions && sync && \ 11 | install-php-extensions mbstring pdo_mysql zip exif pcntl gd memcached bcmath 12 | 13 | # Install dependencies 14 | RUN apt-get update \ 15 | && apt-get install -y --no-install-recommends \ 16 | libz-dev \ 17 | libpq-dev \ 18 | libjpeg-dev \ 19 | libpng-dev \ 20 | libssl-dev \ 21 | libzip-dev \ 22 | unzip \ 23 | zip \ 24 | nodejs \ 25 | && apt-get clean \ 26 | && pecl install redis \ 27 | && docker-php-ext-configure gd \ 28 | && docker-php-ext-configure zip \ 29 | && docker-php-ext-install \ 30 | gd \ 31 | exif \ 32 | opcache \ 33 | pdo_mysql \ 34 | pdo_pgsql \ 35 | pgsql \ 36 | pcntl \ 37 | zip \ 38 | sockets \ 39 | bcmath \ 40 | && docker-php-ext-enable redis \ 41 | && rm -rf /var/lib/apt/lists/*; 42 | 43 | # swich uid and gid to 1000 to not overlap user with host system 44 | RUN usermod -u 1000 www-data && groupmod -g 1000 www-data 45 | 46 | # COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer 47 | COPY --from=composer:latest /usr/bin/composer /usr/bin/composer 48 | 49 | # Hack for logging in Docker 50 | RUN ln -sf /proc/1/fd/1 /var/log/stream.log 51 | 52 | COPY ./docker /docker 53 | RUN chmod 0755 /docker/startup.sh 54 | 55 | # Set working directory 56 | WORKDIR /var/www 57 | RUN chmod -R 0777 /var/www/storage 58 | 59 | COPY . /var/www/ 60 | RUN composer install --no-scripts --optimize-autoloader 61 | 62 | #CMD ["/docker/startup.sh"] 63 | -------------------------------------------------------------------------------- /app/Console/Kernel.php: -------------------------------------------------------------------------------- 1 | command('inspire')->hourly(); 16 | } 17 | 18 | /** 19 | * Register the commands for the application. 20 | */ 21 | protected function commands(): void 22 | { 23 | $this->load(__DIR__.'/Commands'); 24 | 25 | require base_path('routes/console.php'); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/Exceptions/Handler.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | protected $dontFlash = [ 16 | 'current_password', 17 | 'password', 18 | 'password_confirmation', 19 | ]; 20 | 21 | /** 22 | * Register the exception handling callbacks for the application. 23 | */ 24 | public function register(): void 25 | { 26 | $this->reportable(function (Throwable $e) { 27 | // 28 | }); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Http/Controllers/Controller.php: -------------------------------------------------------------------------------- 1 | only(['library_id', 'original_name', 'file_key', 'filename'])); 14 | $libraryFile->saveRawFile($request->raw_content); 15 | $libraryFile->saveConvertedFile(); 16 | $libraryFile->saveEmbeddedFile(); 17 | 18 | return redirect('/'); 19 | } 20 | 21 | public function download(string $fileKey) 22 | { 23 | $libraryFile = LibraryFile::where('file_key', $fileKey)->first(); 24 | if (!$libraryFile) { 25 | return redirect('/'); 26 | } 27 | 28 | return $libraryFile->downloadRawFile(); 29 | } 30 | 31 | public function delete(LibraryFile $libraryFile) 32 | { 33 | $libraryFile->delete(); 34 | $libraryFile->deleteRawFile(); 35 | $libraryFile->deleteConvertedFile(); 36 | $libraryFile->deleteEmbeddedFile(); 37 | 38 | return response()->json(['result' => 1]); 39 | } 40 | 41 | // public function view(LibraryFile $libraryFile) 42 | // { 43 | // return response()->json(['result' => 1, 'name' => $libraryFile->original_name, 'content' => $libraryFile->getConvertedFile()]); 44 | // } 45 | 46 | public function chunks(LibraryFile $libraryFile) 47 | { 48 | return view('library.index'); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/Http/Controllers/FileEditorController.php: -------------------------------------------------------------------------------- 1 | fileChunksEditorService = $fileChunksEditor; 23 | $this->fileChunksEmbeddedEditorService = $fileChunksEmbeddedEditor; 24 | } 25 | 26 | public function upload(FileUploadRequest $request) 27 | { 28 | $libraryFile = LibraryFile::create($request->only(['library_id', 'original_name', 'file_key', 'filename'])); 29 | $libraryFile->saveRawFile($request->raw_content); 30 | 31 | 32 | return redirect('/'); 33 | } 34 | 35 | public function download(string $fileKey) 36 | { 37 | $libraryFile = LibraryFile::where('file_key', $fileKey)->first(); 38 | if (!$libraryFile) { 39 | return redirect('/'); 40 | } 41 | 42 | return $libraryFile->downloadRawFile(); 43 | } 44 | 45 | public function delete(LibraryFile $libraryFile) 46 | { 47 | $libraryFile->delete(); 48 | $libraryFile->deleteRawFile(); 49 | 50 | return redirect('/'); 51 | } 52 | 53 | 54 | public function chunksEdit(LibraryFile $libraryFile) 55 | { 56 | $optimizePercentage = $libraryFile->total_embedded_words 57 | ? round(100 - 100 * (($libraryFile->total_words - ($libraryFile->total_words - $libraryFile->total_embedded_words)) / $libraryFile->total_words)) 58 | : 0; 59 | 60 | return view('file.chunks.edit', [ 61 | 'libraryFile' => $libraryFile, 62 | 'chunks' => $this->fileChunksEditorService->getItemChunked($libraryFile), 63 | 'optimize_percentage' => $optimizePercentage, 64 | ]); 65 | } 66 | 67 | public function chunksUpdate(LibraryFile $libraryFile, ChunkUpdateRequest $request) 68 | { 69 | $data = $this->fileChunksEditorService->reorderDataKeys($request->chunks, $request->chunked_list); 70 | 71 | $chunkSeparator = $libraryFile->library->chunk_separator ?? LibraryFile::DEFAULT_CHUNK_SEPARATOR; 72 | $data = $this->fileChunksEditorService->splitDataBySeparator($data, $chunkSeparator); 73 | 74 | $libraryFile->stop_word = (bool) ($request->optimize ?? false); 75 | $libraryFile->lowercase = (bool) ($request->optimize ?? false); 76 | $libraryFile->strip_tag = (bool) ($request->optimize ?? false); 77 | $libraryFile->strip_punctuation = (bool) ($request->optimize ?? false); 78 | $libraryFile->strip_special_char = (bool) ($request->optimize ?? false); 79 | $libraryFile->chunked_list = $data['chunkedList']; 80 | $libraryFile->save(); 81 | $libraryFile->saveFiles($request->images); 82 | $libraryFile->saveLinks($request->links); 83 | 84 | if (!$this->fileChunksEditorService->updateItemChunked($libraryFile, $data['chunks'])) { 85 | return back()->with('status', 'file-updated-error'); 86 | } 87 | 88 | $this->fileChunksEmbeddedEditorService->execute($libraryFile); 89 | 90 | $libraryFile->total_words = $libraryFile->getTotalRawWords(); 91 | $libraryFile->total_embedded_words = $libraryFile->getTotalEmbeddedWords(); 92 | $libraryFile->save(); 93 | 94 | return back()->with('status', 'file-updated-successfully'); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /app/Http/Controllers/LibraryController.php: -------------------------------------------------------------------------------- 1 | $library]); 14 | } 15 | 16 | public function save(LibrarySaveRequest $request) 17 | { 18 | $library = Library::default(); 19 | $library->temperature = $request->temperature; 20 | $library->chunk_separator = $request->chunk_separator ?? null; 21 | $library->save(); 22 | 23 | return redirect('/'); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Http/Controllers/PlaygroundController.php: -------------------------------------------------------------------------------- 1 | get() 22 | ->mapWithKeys( 23 | fn($providerModel) => [$providerModel->id => $providerModel->name . ' ( ' . $providerModel->input_format . ' -> ' . $providerModel->output_format . ' )'] 24 | ) 25 | ->toArray(); 26 | 27 | return view('playground.index', ['providerModels' => $providerModels]); 28 | } 29 | 30 | public function send(PlaygroundSendRequest $request) 31 | { 32 | $query = $request->q; 33 | $providerModel = $request->provider_model; 34 | 35 | $requestQuery = $filteredQuery = PlaygroundEditorFilterChain::make($query)->handle(); 36 | 37 | $attachments = []; 38 | if ($request->search_type !== 'vector_search') { 39 | $library = Library::default(); 40 | $requestData = $library->getRequestQuery($filteredQuery); 41 | $requestQuery = $requestData['prompt'] ?? ''; 42 | $attachments = $requestData['attachments'] ?? []; 43 | } 44 | 45 | $aiModel = AiModelResolver::make($providerModel->slug)->resolve($requestQuery); 46 | if ($aiModel instanceof NullAiModel) { 47 | return response()->json(['result' => 2, 'answer' => 'Error: This model is not available yet']); 48 | } 49 | 50 | $answer = ''; 51 | try { 52 | $client = AiService::createCompletionFactory(); 53 | if ($aiModel instanceof Gpt4AiModel 54 | || $aiModel instanceof Gpt35TurboAiModel 55 | || $aiModel instanceof Gpt35Turbo16KAiModel) { 56 | $client = AiService::createChatFactory(); 57 | } 58 | $response = $client->send($aiModel->getData()); 59 | if (empty($response->id)) { 60 | return response()->json(['result' => 2, 'answer' => 'Error: No answer from OpenAI']); 61 | } 62 | $answer = $client->getResult(); 63 | } catch (\Exception $e) { 64 | return response()->json(['result' => 2, 'answer' => $e->getMessage()]); 65 | } 66 | 67 | return response()->json(['result' => 1, 'answer' => $answer, 'attachments' => $attachments]); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/Http/Kernel.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | protected $middleware = [ 17 | // \App\Http\Middleware\TrustHosts::class, 18 | \App\Http\Middleware\TrustProxies::class, 19 | \Illuminate\Http\Middleware\HandleCors::class, 20 | \App\Http\Middleware\PreventRequestsDuringMaintenance::class, 21 | \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, 22 | \App\Http\Middleware\TrimStrings::class, 23 | \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, 24 | ]; 25 | 26 | /** 27 | * The application's route middleware groups. 28 | * 29 | * @var array> 30 | */ 31 | protected $middlewareGroups = [ 32 | 'web' => [ 33 | \App\Http\Middleware\EncryptCookies::class, 34 | \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, 35 | \Illuminate\Session\Middleware\StartSession::class, 36 | \Illuminate\View\Middleware\ShareErrorsFromSession::class, 37 | \App\Http\Middleware\VerifyCsrfToken::class, 38 | \Illuminate\Routing\Middleware\SubstituteBindings::class, 39 | ], 40 | 41 | 'api' => [ 42 | // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, 43 | \Illuminate\Routing\Middleware\ThrottleRequests::class.':api', 44 | \Illuminate\Routing\Middleware\SubstituteBindings::class, 45 | ], 46 | ]; 47 | 48 | /** 49 | * The application's middleware aliases. 50 | * 51 | * Aliases may be used instead of class names to conveniently assign middleware to routes and groups. 52 | * 53 | * @var array 54 | */ 55 | protected $middlewareAliases = [ 56 | 'auth' => \App\Http\Middleware\Authenticate::class, 57 | 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 58 | 'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class, 59 | 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, 60 | 'can' => \Illuminate\Auth\Middleware\Authorize::class, 61 | 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 62 | 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class, 63 | 'signed' => \App\Http\Middleware\ValidateSignature::class, 64 | 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 65 | 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 66 | ]; 67 | } 68 | -------------------------------------------------------------------------------- /app/Http/Middleware/Authenticate.php: -------------------------------------------------------------------------------- 1 | expectsJson() ? null : route('login'); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/Http/Middleware/EncryptCookies.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | protected $except = [ 15 | // 16 | ]; 17 | } 18 | -------------------------------------------------------------------------------- /app/Http/Middleware/PreventRequestsDuringMaintenance.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | protected $except = [ 15 | // 16 | ]; 17 | } 18 | -------------------------------------------------------------------------------- /app/Http/Middleware/RedirectIfAuthenticated.php: -------------------------------------------------------------------------------- 1 | check()) { 24 | return redirect(RouteServiceProvider::HOME); 25 | } 26 | } 27 | 28 | return $next($request); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Http/Middleware/TrimStrings.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | protected $except = [ 15 | 'current_password', 16 | 'password', 17 | 'password_confirmation', 18 | ]; 19 | } 20 | -------------------------------------------------------------------------------- /app/Http/Middleware/TrustHosts.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | public function hosts(): array 15 | { 16 | return [ 17 | $this->allSubdomainsOfApplicationUrl(), 18 | ]; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Http/Middleware/TrustProxies.php: -------------------------------------------------------------------------------- 1 | |string|null 14 | */ 15 | protected $proxies; 16 | 17 | /** 18 | * The headers that should be used to detect proxies. 19 | * 20 | * @var int 21 | */ 22 | protected $headers = 23 | Request::HEADER_X_FORWARDED_FOR | 24 | Request::HEADER_X_FORWARDED_HOST | 25 | Request::HEADER_X_FORWARDED_PORT | 26 | Request::HEADER_X_FORWARDED_PROTO | 27 | Request::HEADER_X_FORWARDED_AWS_ELB; 28 | } 29 | -------------------------------------------------------------------------------- /app/Http/Middleware/ValidateSignature.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | protected $except = [ 15 | // 'fbclid', 16 | // 'utm_campaign', 17 | // 'utm_content', 18 | // 'utm_medium', 19 | // 'utm_source', 20 | // 'utm_term', 21 | ]; 22 | } 23 | -------------------------------------------------------------------------------- /app/Http/Middleware/VerifyCsrfToken.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | protected $except = [ 15 | // 16 | ]; 17 | } 18 | -------------------------------------------------------------------------------- /app/Http/Requests/ChunkUpdateRequest.php: -------------------------------------------------------------------------------- 1 | 21 | */ 22 | public function rules(): array 23 | { 24 | return [ 25 | // 26 | ]; 27 | } 28 | 29 | public function passedValidation() 30 | { 31 | $this->images = $this->links = []; 32 | foreach (($this->attachments ?? []) as $chunk => $attachment) { 33 | foreach (($attachment['images'] ?? []) as $index => $image) { 34 | if (empty($image)) continue; 35 | $this->images[$chunk][$index] = $image; 36 | } 37 | foreach (($attachment['links'] ?? []) as $index => $link) { 38 | if (empty($link)) continue; 39 | $this->links[$chunk][$index] = $link; 40 | } 41 | } 42 | 43 | $this->merge([ 44 | 'images' => $this->images, 45 | 'links' => $this->links, 46 | ]); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/Http/Requests/FileUploadRequest.php: -------------------------------------------------------------------------------- 1 | 23 | */ 24 | public function rules(): array 25 | { 26 | return [ 27 | 'library_id' => ['required', 'exists:libraries,id'], 28 | 'file' => ['required', 'max:100000000', 'mimes:txt,csv,pdf'] 29 | ]; 30 | } 31 | 32 | public function messages() 33 | { 34 | return [ 35 | 'file.required' => 'File is required', 36 | 'file.max' => 'Max file size is 100M bytes', 37 | 'file.mimes' => "File can be txt or csv or pdf format", 38 | ]; 39 | } 40 | 41 | public function passedValidation() 42 | { 43 | do { 44 | $fileKey = Str::random(rand(32, 64)); 45 | $checkKey = LibraryFile::where('file_key', $fileKey)->first(); 46 | } while (!empty($checkKey->id)); 47 | 48 | $originalName = request()->file('file')->getClientOriginalName(); 49 | 50 | $this->merge([ 51 | 'file_key' => $fileKey, 52 | 'original_name' => $originalName, 53 | 'filename' => time() . $originalName, 54 | 'raw_content' => request()->file('file')->get(), 55 | ]); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/Http/Requests/LibrarySaveRequest.php: -------------------------------------------------------------------------------- 1 | 21 | */ 22 | public function rules(): array 23 | { 24 | return [ 25 | 'temperature' => ['required', 'numeric', 'between:0.05,1'], 26 | ]; 27 | } 28 | 29 | public function messages() 30 | { 31 | return [ 32 | "temperature.required" => "Creativity is required", 33 | ]; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Http/Requests/PlaygroundSendRequest.php: -------------------------------------------------------------------------------- 1 | 22 | */ 23 | public function rules(): array 24 | { 25 | return [ 26 | 'q' => ['required', 'max:255'], 27 | 'model_id' => ['required', 'exists:provider_models,id'], 28 | 'search_type' => ['required', 'in:rag,vector_search'], 29 | ]; 30 | } 31 | 32 | public function messages() 33 | { 34 | return [ 35 | 'q.required' => 'The query is required', 36 | 'model_id.exists' => 'The model is wrong', 37 | 'search_type.required' => 'The search type is required', 38 | ]; 39 | } 40 | 41 | public function passedValidation() 42 | { 43 | $providerModel = ProviderModel::find(request()->model_id); 44 | 45 | $this->merge([ 46 | 'provider_model' => $providerModel, 47 | ]); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/Models/Library.php: -------------------------------------------------------------------------------- 1 | hasMany(LibraryFile::class, 'library_id'); 21 | } 22 | 23 | public static function default() 24 | { 25 | return Library::first(); 26 | } 27 | 28 | public function getRequestQuery(string $query) 29 | { 30 | if ($this->files->isEmpty()) return $query; 31 | 32 | $client = AiService::createEmbeddingFactory(); 33 | $requestVector = $client->send($query, $this->embedded_model); 34 | $libraryData = array('texts' => [], 'vectors' => []); 35 | 36 | $storage = new EmbeddedStepService(); 37 | foreach ($this->files as $libraryFile) { 38 | $pathJson = $libraryFile->getPathToSavingEmbeddedFile(); 39 | if (!$storage->exists($pathJson)) continue; 40 | $fileData = json_decode($storage->get($pathJson), true); 41 | if (empty($fileData['html']) || empty($fileData['vectors'])) continue; 42 | foreach ($fileData['html'] as $key => $text) { 43 | $libraryData['texts'][] = PlaygroundSendFilterChain::make($text)->handle(); 44 | $libraryData['vectors'][] = (!empty($fileData['vectors'][$key]) ? $fileData['vectors'][$key] : []); 45 | $attachments = (!empty($fileData['meta']['chunks'][$key]) ? $fileData['meta']['chunks'][$key] : []); 46 | foreach ($attachments['images'] as $indexNumber => $imageName) { 47 | $attachments['images'][$indexNumber] = $storage->url( 48 | $libraryFile->getPathToAttachments() 49 | . '/' . $key 50 | . '/' . $indexNumber 51 | . '/' . $imageName 52 | ); 53 | } 54 | $libraryData['attachments'][] = $attachments; 55 | } 56 | 57 | } 58 | 59 | if (empty($libraryData['texts']) || empty($libraryData['vectors'])) { 60 | return $query; 61 | } 62 | 63 | $score = []; 64 | foreach ($libraryData['vectors'] as $key => $libraryVector) { 65 | $result = array_map(function($x, $y) { 66 | return $x * $y; 67 | }, $requestVector, $libraryVector); 68 | $score[$key] = array_sum($result); 69 | } 70 | 71 | //arsort($score); 72 | 73 | $choosenVector = array_key_first($score); 74 | $secondVector = null; 75 | if ($this->chunk_size <= 1500) { 76 | $arrKeys = array_keys($score); 77 | if (!empty($arrKeys[1]) && !empty($libraryData['texts'][$choosenVector]) && strlen($libraryData['texts'][$choosenVector]) <= 2000) { 78 | $secondVector = $arrKeys[1]; 79 | } 80 | } 81 | 82 | $firstChunk = $libraryData['texts'][$choosenVector] ?? ''; 83 | $secondChunk = $libraryData['texts'][$secondVector] ?? ''; 84 | 85 | return [ 86 | 'prompt' => 'Answer the question as truthfully as possible using the provided text' 87 | . "\n\n" . 'Context:' . "\n" 88 | . $firstChunk . 89 | (!empty($secondChunk) ? "\n\n" . $secondChunk : '') 90 | . "\n\n" . 'Q: ' . $query . "\n" . 'A:', 91 | 'attachments' => $libraryData['attachments'][$choosenVector] ?? [], 92 | ]; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /app/Models/LibraryFileChunkAttachment.php: -------------------------------------------------------------------------------- 1 | library_id 18 | . '/' 19 | . $this->id; 20 | } 21 | 22 | public function saveFiles(array $files): bool 23 | { 24 | $embeddedStorage = new EmbeddedStepService(); 25 | $embeddedFile = $this->getPathToSavingEmbeddedFile(); 26 | if (!$embeddedStorage->exists($embeddedFile)) return false; 27 | 28 | $rawStorage = new UploadedStepService(); 29 | 30 | $embeddedData = json_decode($embeddedStorage->get($embeddedFile), true); 31 | 32 | foreach ($files as $chunkNumber => $chunkFiles) { 33 | foreach ($chunkFiles as $index => $chunkFile) { 34 | $fileName = $chunkFile->getClientOriginalName(); 35 | $path = $this->getPathToAttachments() . '/' . $chunkNumber . '/'. $index . '/' . $fileName; 36 | $rawStorage->upload($path, $chunkFile->getContent(), StorageDriver::VISIBILITY_PUBLIC); 37 | if (isset($embeddedData['meta']['chunks'][$chunkNumber]['images'][$index])) { 38 | $path = $this->getPathToAttachments() . '/' . $index . '/'. $embeddedData['meta']['chunks'][$chunkNumber]['images'][$index]; 39 | $rawStorage->delete($path); 40 | } 41 | $embeddedData['meta']['chunks'][$chunkNumber]['images'][$index] = $fileName; 42 | } 43 | } 44 | 45 | $embeddedStorage->upload($embeddedFile, json_encode($embeddedData)); 46 | 47 | return true; 48 | } 49 | 50 | public function getAttachments(): array 51 | { 52 | $storage = new EmbeddedStepService(); 53 | $embeddedFile = $this->getPathToSavingEmbeddedFile(); 54 | if (!$storage->exists($embeddedFile)) return []; 55 | 56 | $embeddedData = json_decode($storage->get($embeddedFile), true); 57 | 58 | $attachments = []; 59 | $chunks = $embeddedData['meta']['chunks'] ?? []; 60 | foreach ($chunks as $chunkNumber => $chunk) { 61 | foreach (($chunk['images'] ?? []) as $imageNumber => $imageName) { 62 | $path = $this->getPathToAttachments() . '/' . $chunkNumber . '/'. $imageNumber . '/' . $imageName; 63 | $attachments[$chunkNumber]['images'][$imageNumber] = $storage->url($path); 64 | } 65 | $attachments[$chunkNumber]['links'] = $chunk['links'] ?? [];; 66 | } 67 | 68 | return $attachments; 69 | } 70 | 71 | public function saveLinks(array $links): bool 72 | { 73 | $storage = new EmbeddedStepService(); 74 | $embeddedFile = $this->getPathToSavingEmbeddedFile(); 75 | if (!$storage->exists($embeddedFile)) return false; 76 | 77 | $embeddedData = json_decode($storage->get($embeddedFile), true); 78 | 79 | foreach ($links as $chunkNumber => $chunkLinks) { 80 | foreach ($chunkLinks as $indexNumber => $chunkLink) { 81 | $embeddedData['meta']['chunks'][$chunkNumber]['links'][$indexNumber] = $chunkLink; 82 | } 83 | } 84 | 85 | $storage->upload($embeddedFile, json_encode($embeddedData)); 86 | 87 | return true; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /app/Models/Provider.php: -------------------------------------------------------------------------------- 1 | orderBy('name'); 18 | }); 19 | } 20 | 21 | public function provider(): BelongsTo 22 | { 23 | return $this->belongsTo(Provider::class, 'provider_id'); 24 | } 25 | 26 | public function scopeActive($query) 27 | { 28 | return $query->where('active', true); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Models/User.php: -------------------------------------------------------------------------------- 1 | 19 | */ 20 | protected $fillable = [ 21 | 'name', 22 | 'email', 23 | 'password', 24 | ]; 25 | 26 | /** 27 | * The attributes that should be hidden for serialization. 28 | * 29 | * @var array 30 | */ 31 | protected $hidden = [ 32 | 'password', 33 | 'remember_token', 34 | ]; 35 | 36 | /** 37 | * The attributes that should be cast. 38 | * 39 | * @var array 40 | */ 41 | protected $casts = [ 42 | 'email_verified_at' => 'datetime', 43 | 'password' => 'hashed', 44 | ]; 45 | } 46 | -------------------------------------------------------------------------------- /app/Providers/AppServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->environment('production') 23 | || $this->app->environment('dev') 24 | || $this->app->environment('stage') 25 | ) { 26 | $this->app['request']->server->set('HTTPS', 'on'); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/Providers/AuthServiceProvider.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | protected $policies = [ 16 | // 17 | ]; 18 | 19 | /** 20 | * Register any authentication / authorization services. 21 | */ 22 | public function boot(): void 23 | { 24 | // 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Providers/BroadcastServiceProvider.php: -------------------------------------------------------------------------------- 1 | > 16 | */ 17 | protected $listen = [ 18 | Registered::class => [ 19 | SendEmailVerificationNotification::class, 20 | ], 21 | ]; 22 | 23 | /** 24 | * Register any events for your application. 25 | */ 26 | public function boot(): void 27 | { 28 | // 29 | } 30 | 31 | /** 32 | * Determine if events and listeners should be automatically discovered. 33 | */ 34 | public function shouldDiscoverEvents(): bool 35 | { 36 | return false; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/Providers/RouteServiceProvider.php: -------------------------------------------------------------------------------- 1 | by($request->user()?->id ?: $request->ip()); 29 | }); 30 | 31 | $this->routes(function () { 32 | Route::middleware('api') 33 | ->prefix('api') 34 | ->group(base_path('routes/api.php')); 35 | 36 | Route::middleware('web') 37 | ->group(base_path('routes/web.php')); 38 | }); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/Services/Ai/AiService.php: -------------------------------------------------------------------------------- 1 | apiKey = config('services.openai.api_key'); 19 | } 20 | 21 | public function send(array $data): mixed 22 | { 23 | $client = OpenAI::client($this->apiKey); 24 | 25 | $response = $client->chat()->create($data); 26 | 27 | $result = trim($response->choices[0]->message->content ?? ''); 28 | 29 | if (strpos($result, "\n\n") !== false) { 30 | $result = '

' . str_replace("\n\n", '

', $result) . '

'; 31 | } 32 | if (strpos($result, "\n") !== false) { 33 | $result = str_replace("\n", '
', $result); 34 | } 35 | $this->result = $result; 36 | 37 | $this->tokens = $response->usage->totalTokens ?? 0; 38 | 39 | return $response; 40 | } 41 | 42 | public function getResult(): string 43 | { 44 | return trim($this->result); 45 | } 46 | 47 | public function getTotalTokens(): int 48 | { 49 | return $this->tokens; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/Services/Ai/Completions/AiCompletion.php: -------------------------------------------------------------------------------- 1 | apiKey = config('services.openai.api_key'); 19 | } 20 | 21 | public function send(array $data): mixed 22 | { 23 | $client = OpenAI::client($this->apiKey); 24 | 25 | $response = $client->completions()->create($data); 26 | 27 | $result = trim($response->choices[0]->text ?? ''); 28 | 29 | if (strpos($result, "\n\n") !== false) { 30 | $result = '

' . str_replace("\n\n", '

', $result) . '

'; 31 | } 32 | if (strpos($result, "\n") !== false) { 33 | $result = str_replace("\n", '
', $result); 34 | } 35 | $this->result = $result; 36 | 37 | $this->tokens = $response->usage->totalTokens ?? 0; 38 | 39 | return $response; 40 | } 41 | 42 | public function getResult(): string 43 | { 44 | return trim($this->result); 45 | } 46 | 47 | public function getTotalTokens(): int 48 | { 49 | return $this->tokens; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/Services/Ai/Embeddings/AiEmbedding.php: -------------------------------------------------------------------------------- 1 | apiKey = config('services.openai.api_key'); 15 | } 16 | 17 | public function send(string $request, string $model): array 18 | { 19 | $client = OpenAI::client($this->apiKey); 20 | 21 | $response = $client->embeddings()->create([ 22 | 'model' => $model, 23 | 'input' => $request, 24 | ]); 25 | 26 | return $response->embeddings[0]->embedding ?? []; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/Services/Ai/Models/AiModel.php: -------------------------------------------------------------------------------- 1 | slug = $slug; 13 | } 14 | 15 | public static function make(string $slug): AiModelResolver 16 | { 17 | return new static($slug); 18 | } 19 | 20 | public function resolve(string $query): AiModel 21 | { 22 | switch ($this->slug) { 23 | case 'gpt-3.5-turbo': 24 | return new Gpt35TurboAiModel($query); 25 | case 'gpt-3.5-turbo-16k': 26 | return new Gpt35Turbo16KAiModel($query); 27 | case 'gpt-4': 28 | return new Gpt4AiModel($query); 29 | case 'text-davinci-003': 30 | return new TextDavinci003AiModel($query); 31 | case 'text-davinci-002': 32 | return new TextDavinci002AiModel($query); 33 | case 'text-curie-001': 34 | return new TextCuris001AiModel($query); 35 | case 'text-babbage-001': 36 | return new TextBabbage001AiModel($query); 37 | case 'text-ada-001': 38 | return new TextAda001AiModel($query); 39 | } 40 | 41 | return new NullAiModel(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/Services/Ai/Models/BaseAiModel.php: -------------------------------------------------------------------------------- 1 | query = $query; 15 | } 16 | 17 | abstract public function getData(): array; 18 | 19 | protected function getDifference(): int 20 | { 21 | $length = (int) round(strlen($this->query)/0.75/2); 22 | return $this->length - $length; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/Services/Ai/Models/Gpt35Turbo16KAiModel.php: -------------------------------------------------------------------------------- 1 | 'user', 'content' => $this->query]; 10 | $messages[] = ['role' => 'system', 'content' => 'You are a helpful assistant']; 11 | $messages = array_reverse($messages); 12 | return [ 13 | 'model' => 'gpt-3.5-turbo-16k', 14 | 'messages' => $messages, 15 | ]; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/Services/Ai/Models/Gpt35TurboAiModel.php: -------------------------------------------------------------------------------- 1 | 'user', 'content' => $this->query]; 10 | $messages[] = ['role' => 'system', 'content' => 'You are a helpful assistant']; 11 | $messages = array_reverse($messages); 12 | return [ 13 | 'model' => 'gpt-3.5-turbo', 14 | 'messages' => $messages 15 | ]; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/Services/Ai/Models/Gpt4AiModel.php: -------------------------------------------------------------------------------- 1 | 'user', 'content' => $this->query]; 10 | $messages[] = ['role' => 'system', 'content' => 'You are a helpful assistant']; 11 | $messages = array_reverse($messages); 12 | return [ 13 | 'model' => 'gpt-4', 14 | 'messages' => $messages 15 | ]; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/Services/Ai/Models/NullAiModel.php: -------------------------------------------------------------------------------- 1 | length = 2000; 13 | } 14 | 15 | /** 16 | * @throws \Exception 17 | */ 18 | public function getData(): array 19 | { 20 | $difference = $this->getDifference(); 21 | if ($difference < self::MIN_DIFFERENCE) { 22 | throw new \Exception('Error: Your request is too long'); 23 | } 24 | 25 | return [ 26 | 'prompt' => $this->query, 27 | 'model' => 'text-ada-001', 28 | 'max_tokens' => $difference, 29 | 'temperature' => (float) 0.7, 30 | ]; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Services/Ai/Models/TextBabbage001AiModel.php: -------------------------------------------------------------------------------- 1 | length = 2000; 13 | } 14 | /** 15 | * @throws \Exception 16 | */ 17 | public function getData(): array 18 | { 19 | $difference = $this->getDifference(); 20 | if ($difference < self::MIN_DIFFERENCE) { 21 | throw new \Exception('Error: Your request is too long'); 22 | } 23 | 24 | return [ 25 | 'prompt' => $this->query, 26 | 'model' => 'text-babbage-001', 27 | 'max_tokens' => $difference, 28 | 'temperature' => (float) 0.7, 29 | ]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/Services/Ai/Models/TextCuris001AiModel.php: -------------------------------------------------------------------------------- 1 | length = 2000; 13 | } 14 | 15 | /** 16 | * @throws \Exception 17 | */ 18 | public function getData(): array 19 | { 20 | $difference = $this->getDifference(); 21 | if ($difference < self::MIN_DIFFERENCE) { 22 | throw new \Exception('Error: Your request is too long'); 23 | } 24 | 25 | return [ 26 | 'prompt' => $this->query, 27 | 'model' => 'text-curie-001', 28 | 'max_tokens' => $difference, 29 | 'temperature' => (float) 0.7, 30 | ]; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Services/Ai/Models/TextDavinci002AiModel.php: -------------------------------------------------------------------------------- 1 | length = 4000; 13 | } 14 | 15 | /** 16 | * @throws \Exception 17 | */ 18 | public function getData(): array 19 | { 20 | $difference = $this->getDifference(); 21 | if ($difference < self::MIN_DIFFERENCE) { 22 | throw new \Exception('Error: Your request is too long'); 23 | } 24 | 25 | return [ 26 | 'prompt' => $this->query, 27 | 'model' => 'text-davinci-002', 28 | 'max_tokens' => $difference, 29 | 'temperature' => (float) 0.7, 30 | ]; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Services/Ai/Models/TextDavinci003AiModel.php: -------------------------------------------------------------------------------- 1 | length = 4000; 13 | } 14 | /** 15 | * @throws \Exception 16 | */ 17 | public function getData(): array 18 | { 19 | $difference = $this->getDifference(); 20 | if ($difference < self::MIN_DIFFERENCE) { 21 | throw new \Exception('Error: Your request is too long'); 22 | } 23 | 24 | return [ 25 | 'prompt' => $this->query, 26 | 'model' => 'text-davinci-003', 27 | 'max_tokens' => $difference, 28 | 'temperature' => (float) 0.7, 29 | ]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/Services/Converters/ConverterResolver.php: -------------------------------------------------------------------------------- 1 | rawFile = $rawFile; 17 | } 18 | 19 | public static function make(string $rawFile): ConverterResolver 20 | { 21 | return new static($rawFile); 22 | } 23 | 24 | public function resolve(): ConverterHandler 25 | { 26 | $extension = explode('.', basename($this->rawFile))[1] ?? ''; 27 | switch ($extension) { 28 | case 'pdf': 29 | return new PdfConverterHandler($this->rawFile); 30 | case 'csv': 31 | return new CsvConverterHandler($this->rawFile); 32 | } 33 | 34 | return new TextConverterHandler($this->rawFile); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/Services/Converters/Handlers/BaseConverterHandler.php: -------------------------------------------------------------------------------- 1 | rawFile = $rawFile; 12 | } 13 | 14 | abstract public function handle(string $convertedFile): ConverterHandler; 15 | } 16 | -------------------------------------------------------------------------------- /app/Services/Converters/Handlers/ConverterHandler.php: -------------------------------------------------------------------------------- 1 | copy($convertedFile, $storage->get($this->rawFile)); 14 | 15 | return $this; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/Services/Converters/Handlers/PdfConverterHandler.php: -------------------------------------------------------------------------------- 1 | parseFile($storage->path($this->rawFile)); 16 | 17 | $storage->copy($convertedFile, $pdf->getText()); 18 | 19 | return $this; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/Services/Converters/Handlers/TextConverterHandler.php: -------------------------------------------------------------------------------- 1 | copy($convertedFile, $storage->get($this->rawFile)); 14 | 15 | return $this; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/Services/Editors/BaseFileChunks.php: -------------------------------------------------------------------------------- 1 | storageService = $uploadedStepService; 17 | $this->embeddedStorageService = $embeddedStepService; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/Services/Editors/FileChunksEditor.php: -------------------------------------------------------------------------------- 1 | getPathToSavingEmbeddedFile(); 15 | 16 | $embeddedFileHtml = []; 17 | if ($this->embeddedStorageService->exists($embeddedFilePath)) { 18 | $embeddedFile = json_decode($this->embeddedStorageService->get($embeddedFilePath)); 19 | 20 | if (!empty($embeddedFile->html)) { 21 | foreach ($embeddedFile->html as $value) { 22 | $embeddedFileHtml[] = str_replace(PHP_EOL, '
', $value); 23 | } 24 | } 25 | } 26 | 27 | return [ 28 | 'html' => $embeddedFileHtml, 29 | 'texts' => $embeddedFile->texts, 30 | 'attachments' => $libraryFile->getAttachments(), 31 | ]; 32 | } 33 | 34 | public function updateItemChunked(LibraryFile $libraryFile, $aFileData) 35 | { 36 | $embeddedFilePath = $libraryFile->getPathToSavingEmbeddedFile(); 37 | $embeddedFile = json_decode($this->embeddedStorageService->get($embeddedFilePath)); 38 | $embeddedFile->html = $aFileData; 39 | 40 | return $this->embeddedStorageService->upload($embeddedFilePath, json_encode($embeddedFile)); 41 | } 42 | 43 | /** 44 | * @param array $requestChunks 45 | * @param array|null $requestChunkedList 46 | * @return array[] 47 | */ 48 | public function reorderDataKeys(array $requestChunks, ?array $requestChunkedList) : array 49 | { 50 | $chunks = $chunkedList = []; 51 | $currentKey = 0; 52 | foreach ($requestChunks as $key => $chunk) { 53 | $chunks[$currentKey] = $chunk; 54 | if (isset($requestChunkedList[$key])) { 55 | $chunkedList[$currentKey] = (string)$currentKey; 56 | } 57 | $currentKey++; 58 | } 59 | 60 | return [ 61 | 'chunks' => $chunks, 62 | 'chunkedList' => $chunkedList, 63 | ]; 64 | } 65 | 66 | /** 67 | * @param array $chunks 68 | * @param string $chunkSeparator 69 | * @return array[] 70 | */ 71 | public function splitDataBySeparator(array $data, string $chunkSeparator) : array 72 | { 73 | $chunksBySeparators = $chunkedListBySeparators = []; 74 | $currentKey = 0; 75 | 76 | foreach ($data['chunks'] as $key => $chunk) { 77 | $currentChunkedListStatus = isset($data['chunkedList'][$key]); 78 | 79 | $chunkParts = explode($chunkSeparator, $chunk); 80 | 81 | if (count($chunkParts) == 1) { 82 | $chunksBySeparators[$currentKey] = $chunk; 83 | if ($currentChunkedListStatus) { 84 | $chunkedListBySeparators[$currentKey] = (string)$currentKey; 85 | } 86 | $currentKey++; 87 | continue; 88 | } 89 | 90 | foreach ($chunkParts as $value) { 91 | $chunksBySeparators[$currentKey] = $value; 92 | if ($currentChunkedListStatus) { 93 | $chunkedListBySeparators[$currentKey] = (string)$currentKey; 94 | } 95 | $currentKey++; 96 | } 97 | } 98 | 99 | return [ 100 | 'chunks' => $chunksBySeparators, 101 | 'chunkedList' => $chunkedListBySeparators, 102 | ]; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /app/Services/Editors/FileChunksEmbeddedEditor.php: -------------------------------------------------------------------------------- 1 | chunked = LibraryFile::STATUS_CHUNKED_PROCESSING; 17 | $libraryFile->save(); 18 | 19 | $embeddedFilePath = $libraryFile->getPathToSavingEmbeddedFile(); 20 | $embeddedFile = json_decode($this->embeddedStorageService->get($embeddedFilePath)); 21 | if (empty($embeddedFile->html)) { 22 | return $this->handleSuccessResult($libraryFile); 23 | } 24 | 25 | $client = AiService::createEmbeddingFactory(); 26 | $texts = []; 27 | $vectors = []; 28 | foreach ($embeddedFile->html as $key => $chunk) { 29 | 30 | // 1. Filter chunk by checkboxes 31 | if (isset($libraryFile->chunked_list) && !in_array($key, $libraryFile->chunked_list)) { 32 | $texts[] = ''; 33 | $vectors[] = []; 34 | continue; 35 | } 36 | 37 | // 2. Filter chunk content by colors 38 | $texts[$key] = ChunkEditorFilterChain::make(self::prepareCustomChunk($chunk), $libraryFile)->handle(); 39 | 40 | if (empty($texts[$key])) { 41 | $vectors[] = []; 42 | continue; 43 | } 44 | 45 | $vectors[$key] = []; 46 | try { 47 | $response = $client->send($texts[$key], $libraryFile->library->embedded_model); 48 | if (!empty($response)) { 49 | $vectors[$key] = $response; 50 | } 51 | } catch (\Exception $e) { 52 | Log::error($e->getMessage() . ' ' . $e->getTraceAsString()); 53 | } 54 | } 55 | 56 | $embeddedFile->texts = $texts; 57 | $embeddedFile->vectors = $vectors; 58 | $this->embeddedStorageService->upload($embeddedFilePath, json_encode($embeddedFile)); 59 | 60 | return $this->handleSuccessResult($libraryFile); 61 | } 62 | 63 | /** 64 | * @param LibraryFile $libraryFile 65 | * @return bool 66 | */ 67 | private function handleSuccessResult(LibraryFile $libraryFile) : bool 68 | { 69 | $libraryFile->chunked = LibraryFile::STATUS_CHUNKED_OK; 70 | $libraryFile->save(); 71 | return true; 72 | } 73 | 74 | /** 75 | * @param LibraryFile $library 76 | * @return int 77 | */ 78 | public static function prepareCustomChunk($chunk) 79 | { 80 | // removed hidden (red) text 81 | $chunk = preg_replace('/([^<]+)<\/span>/', '', $chunk); 82 | 83 | return strip_tags(trim($chunk)); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /app/Services/Editors/Filters/Chains/ChunkEditorFilterChain.php: -------------------------------------------------------------------------------- 1 | rawData = $rawData; 29 | 30 | $this->isLowerCase = $libraryFile->lowercase; 31 | $this->isStopWords = $libraryFile->stop_word; 32 | $this->isStripTag = $libraryFile->strip_tag; 33 | $this->isStripPunctuation = $libraryFile->strip_punctuation; 34 | $this->isStripSpecialChar = $libraryFile->strip_special_char; 35 | } 36 | 37 | public static function make(string $rawData, LibraryFile $libraryFile) 38 | { 39 | return new static($rawData, $libraryFile); 40 | } 41 | 42 | public function handle(): string 43 | { 44 | $data = $this->rawData; 45 | if ($this->isLowerCase) { 46 | $data = (string) (new StripTagEditorFilter($data))->filter(); 47 | } 48 | if ($this->isLowerCase) { 49 | $data = (string) (new StripSpecialEditorFilter($data))->filter(); 50 | } 51 | if ($this->isLowerCase) { 52 | $data = (string) (new StripPunctEditorFilter($data))->filter(); 53 | } 54 | if ($this->isLowerCase) { 55 | $data = (string) (new LowerCaseEditorFilter($data))->filter(); 56 | } 57 | if ($this->isStopWords) { 58 | $data = (string) (new StopWordEditorFilter($data))->filter(); 59 | } 60 | 61 | return $data; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /app/Services/Editors/Filters/Chains/EditorFilterChain.php: -------------------------------------------------------------------------------- 1 | rawData = $rawData; 12 | } 13 | 14 | public static function make(string $rawData) 15 | { 16 | return new static($rawData); 17 | } 18 | 19 | public function handle(): string 20 | { 21 | return $this->rawData; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/Services/Editors/Filters/Chains/PlaygroundEditorFilterChain.php: -------------------------------------------------------------------------------- 1 | rawData = $rawData; 12 | } 13 | 14 | public static function make(string $rawData) 15 | { 16 | return new static($rawData); 17 | } 18 | 19 | public function handle(): string 20 | { 21 | return $this->rawData; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/Services/Editors/Filters/Chains/PlaygroundSendFilterChain.php: -------------------------------------------------------------------------------- 1 | ([^<]+)<\/span>/', '', $this->rawData); 22 | 23 | // removed active (green) text 24 | $text = preg_replace('/([^<]+)<\/span>/', '', $text); 25 | 26 | return (string) (new StripTagEditorFilter($text))->filter(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/Services/Editors/Filters/EditorFilter.php: -------------------------------------------------------------------------------- 1 | data = $data; 13 | } 14 | 15 | public function filter(): EditorFilter 16 | { 17 | $this->filterData = mb_strtolower($this->data); 18 | 19 | return $this; 20 | } 21 | 22 | public function __toString(): string 23 | { 24 | return trim($this->filterData); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Services/Editors/Filters/StripPunctEditorFilter.php: -------------------------------------------------------------------------------- 1 | data = $data; 13 | } 14 | 15 | public function filter(): EditorFilter 16 | { 17 | $this->filterData = preg_replace('/[[:punct:]]/', ' ', $this->data); 18 | $this->filterData = preg_replace('/[ ]{2,}/', ' ', $this->filterData); 19 | 20 | return $this; 21 | } 22 | 23 | public function __toString(): string 24 | { 25 | return trim($this->filterData); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/Services/Editors/Filters/StripSpecialEditorFilter.php: -------------------------------------------------------------------------------- 1 | data = $data; 13 | } 14 | 15 | public function filter(): EditorFilter 16 | { 17 | $this->filterData = preg_replace('/[@$!%*#?&]/', '', $this->data); 18 | 19 | return $this; 20 | } 21 | 22 | public function __toString(): string 23 | { 24 | return trim($this->filterData); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Services/Editors/Filters/StripTagEditorFilter.php: -------------------------------------------------------------------------------- 1 | data = $data; 13 | } 14 | 15 | public function filter(): EditorFilter 16 | { 17 | $this->filterData = strip_tags($this->data); 18 | 19 | return $this; 20 | } 21 | 22 | public function __toString(): string 23 | { 24 | return trim($this->filterData); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Services/Storage/Adapters/EmbeddedStepService.php: -------------------------------------------------------------------------------- 1 | exec()->getResult(); 23 | } 24 | 25 | public function uploadFromStream(string $path, $sourceStream): mixed 26 | { 27 | $event = new UploadStreamEmbeddedStorageEvent($path, $sourceStream); 28 | 29 | return $event->exec()->getResult(); 30 | } 31 | 32 | public function copy(string $path, string $existedFile): bool 33 | { 34 | $event = new CopyEmbeddedStorageEvent($path, $existedFile); 35 | 36 | return $event->exec()->getResult(); 37 | } 38 | 39 | public function download(string $path, string $originalName) 40 | { 41 | $event = new DownloadEmbeddedStorageEvent($path, $originalName); 42 | 43 | return $event->exec()->getResult(); 44 | } 45 | 46 | public function exists(string $path): bool 47 | { 48 | $event = new ExistsEmbeddedStorageEvent($path); 49 | 50 | return $event->exec()->getResult(); 51 | } 52 | 53 | public function get(string $path): string 54 | { 55 | $event = new GetEmbeddedStorageEvent($path); 56 | 57 | return $event->exec()->getResult(); 58 | } 59 | 60 | public function delete(string $path): bool 61 | { 62 | $event = new DeleteEmbeddedStorageEvent($path); 63 | 64 | return $event->exec()->getResult(); 65 | } 66 | 67 | public function url(string $path): string 68 | { 69 | $event = new UrlEmbeddedStorageEvent($path); 70 | return $event->exec()->getResult(); 71 | } 72 | 73 | public function path(string $path): string 74 | { 75 | $event = new PathEmbeddedStorageEvent($path); 76 | 77 | return $event->exec()->getResult(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /app/Services/Storage/Adapters/StorageStepService.php: -------------------------------------------------------------------------------- 1 | exec()->getResult(); 22 | } 23 | 24 | public function uploadFromStream(string $path, $sourceStream): mixed 25 | { 26 | $event = new UploadStreamRawStorageEvent($path, $sourceStream); 27 | 28 | return $event->exec()->getResult(); 29 | } 30 | 31 | public function copy(string $path, string $existedFile): bool 32 | { 33 | $event = new CopyRawStorageEvent($path, $existedFile); 34 | 35 | return $event->exec()->getResult(); 36 | } 37 | 38 | public function download(string $path, string $originalName) 39 | { 40 | $event = new DownloadRawStorageEvent($path, $originalName); 41 | 42 | return $event->exec()->getResult(); 43 | } 44 | 45 | public function exists(string $path): bool 46 | { 47 | $event = new ExistsRawStorageEvent($path); 48 | 49 | return $event->exec()->getResult(); 50 | } 51 | 52 | public function get(string $path): string 53 | { 54 | $event = new GetRawStorageEvent($path); 55 | 56 | return $event->exec()->getResult(); 57 | } 58 | 59 | public function delete(string $path): bool 60 | { 61 | $event = new DeleteRawStorageEvent($path); 62 | 63 | return $event->exec()->getResult(); 64 | } 65 | 66 | public function url(string $path): string 67 | { 68 | $event = new UrlRawStorageEvent($path); 69 | 70 | return $event->exec()->getResult(); 71 | } 72 | 73 | public function path(string $path): string 74 | { 75 | $event = new PathRawStorageEvent($path); 76 | 77 | return $event->exec()->getResult(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /app/Services/Storage/Drivers/LocalStorageDriver.php: -------------------------------------------------------------------------------- 1 | put($path, $file, $visibility); 15 | } 16 | 17 | public function uploadFromStream(string $path, $sourceStream): mixed 18 | { 19 | Storage::disk(self::DISK_LOCAL)->getDriver()->writeStream($path, $sourceStream); 20 | return $this->exists($path); 21 | } 22 | 23 | public function copy(string $path, $existedFile): bool 24 | { 25 | return Storage::disk(self::DISK_LOCAL)->put($path, $existedFile); 26 | } 27 | 28 | public function download(string $path, $originalName): mixed 29 | { 30 | return Storage::disk(self::DISK_LOCAL)->download($path, $originalName); 31 | } 32 | 33 | public function exists(string $path) : bool 34 | { 35 | return Storage::disk(self::DISK_LOCAL)->exists($path); 36 | } 37 | 38 | public function get(string $path): mixed 39 | { 40 | return Storage::disk(self::DISK_LOCAL)->get($path); 41 | } 42 | 43 | public function delete(string $path): bool 44 | { 45 | return Storage::disk(self::DISK_LOCAL)->delete($path); 46 | } 47 | 48 | public function url(string $path): string 49 | { 50 | return Storage::disk(self::DISK_LOCAL)->url($path); 51 | } 52 | 53 | public function path(string $path): string 54 | { 55 | return Storage::disk(self::DISK_LOCAL)->path($path); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/Services/Storage/Drivers/StorageDriver.php: -------------------------------------------------------------------------------- 1 | setConsumers($path, $existedFile); 17 | } 18 | 19 | public function exec(): StorageEvent 20 | { 21 | foreach ($this->consumers as $consumer) { 22 | $consumer->handle(); 23 | $result = $consumer->isSuccessful(); 24 | $this->results[] = $result; 25 | } 26 | 27 | return $this; 28 | } 29 | 30 | public function getResult(): bool 31 | { 32 | return !in_array(false, $this->results); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/Services/Storage/Events/BaseDeleteStorageEvent.php: -------------------------------------------------------------------------------- 1 | setConsumers($path); 17 | } 18 | 19 | public function exec(): StorageEvent 20 | { 21 | foreach ($this->consumers as $consumer) { 22 | $consumer->handle(); 23 | $result = $consumer->isSuccessful(); 24 | $this->results[] = $result; 25 | } 26 | 27 | return $this; 28 | } 29 | 30 | public function getResult(): bool 31 | { 32 | return !in_array(false, $this->results); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/Services/Storage/Events/BaseDownloadStorageEvent.php: -------------------------------------------------------------------------------- 1 | setConsumers($path, $originalName); 17 | 18 | $this->result = response()->json([]); 19 | } 20 | 21 | public function exec(): StorageEvent 22 | { 23 | foreach ($this->consumers as $consumer) { 24 | $consumer->handle(); 25 | $result = $consumer->getResult(); 26 | if ($result) { 27 | $this->result = $result; 28 | } 29 | } 30 | 31 | return $this; 32 | } 33 | 34 | public function getResult(): mixed 35 | { 36 | return $this->result; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/Services/Storage/Events/BaseExistsStorageEvent.php: -------------------------------------------------------------------------------- 1 | setConsumers($path); 17 | } 18 | 19 | public function exec(): StorageEvent 20 | { 21 | foreach ($this->consumers as $consumer) { 22 | $consumer->handle(); 23 | $result = $consumer->isSuccessful(); 24 | $this->results[] = $result; 25 | } 26 | 27 | return $this; 28 | } 29 | 30 | public function getResult(): bool 31 | { 32 | return !in_array(false, $this->results); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/Services/Storage/Events/BaseGetStorageEvent.php: -------------------------------------------------------------------------------- 1 | setConsumers($path); 17 | } 18 | 19 | public function exec(): StorageEvent 20 | { 21 | foreach ($this->consumers as $consumer) { 22 | $consumer->handle(); 23 | $result = $consumer->getResult(); 24 | if ($result) { 25 | $this->result = $result; 26 | } 27 | } 28 | 29 | return $this; 30 | } 31 | 32 | public function getResult(): string 33 | { 34 | return $this->result; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/Services/Storage/Events/BasePathStorageEvent.php: -------------------------------------------------------------------------------- 1 | setConsumers($path); 17 | } 18 | 19 | public function exec(): StorageEvent 20 | { 21 | foreach ($this->consumers as $consumer) { 22 | $consumer->handle(); 23 | $result = $consumer->getResult(); 24 | if ($result) { 25 | $this->result = $result; 26 | } 27 | } 28 | 29 | return $this; 30 | } 31 | 32 | public function getResult(): string 33 | { 34 | return $this->result; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/Services/Storage/Events/BaseUploadStorageEvent.php: -------------------------------------------------------------------------------- 1 | setConsumers($path, $file, $visibility); 17 | } 18 | 19 | public function exec(): StorageEvent 20 | { 21 | foreach ($this->consumers as $consumer) { 22 | $consumer->handle(); 23 | $result = $consumer->isSuccessful(); 24 | $this->results[] = $result; 25 | } 26 | 27 | return $this; 28 | } 29 | 30 | public function getResult(): bool 31 | { 32 | return !in_array(false, $this->results); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/Services/Storage/Events/BaseUploadStreamStorageEvent.php: -------------------------------------------------------------------------------- 1 | setConsumers($path, $sourceStream); 17 | } 18 | 19 | public function exec(): StorageEvent 20 | { 21 | foreach ($this->consumers as $consumer) { 22 | $consumer->handle(); 23 | $result = $consumer->isSuccessful(); 24 | $this->results[] = $result; 25 | } 26 | 27 | return $this; 28 | } 29 | 30 | public function getResult(): bool 31 | { 32 | return !in_array(false, $this->results); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/Services/Storage/Events/Copy/CopyEmbeddedStorageEvent.php: -------------------------------------------------------------------------------- 1 | consumers = [ 15 | new CopyEmbeddedLocalStorageHandler(new LocalStorageDriver(), $path, $existedFile), 16 | ]; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Services/Storage/Events/Copy/CopyRawStorageEvent.php: -------------------------------------------------------------------------------- 1 | consumers = [ 15 | new CopyRawLocalStorageHandler(new LocalStorageDriver(), $path, $existedFile), 16 | ]; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Services/Storage/Events/Delete/DeleteEmbeddedStorageEvent.php: -------------------------------------------------------------------------------- 1 | consumers = [ 15 | new DeleteEmbeddedLocalStorageHandler(new LocalStorageDriver(), $path), 16 | ]; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Services/Storage/Events/Delete/DeleteRawStorageEvent.php: -------------------------------------------------------------------------------- 1 | consumers = [ 15 | new DeleteRawLocalStorageHandler(new LocalStorageDriver(), $path), 16 | ]; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Services/Storage/Events/Download/DownloadEmbeddedStorageEvent.php: -------------------------------------------------------------------------------- 1 | consumers = [ 14 | new DownloadEmbeddedLocalStorageHandler(new LocalStorageDriver(), $path, $originalName), 15 | ]; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/Services/Storage/Events/Download/DownloadRawStorageEvent.php: -------------------------------------------------------------------------------- 1 | consumers = [ 15 | new DownloadRawLocalStorageHandler(new LocalStorageDriver(), $path, $originalName), 16 | ]; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Services/Storage/Events/Exists/ExistsEmbeddedStorageEvent.php: -------------------------------------------------------------------------------- 1 | consumers = [ 15 | new ExistsEmbeddedLocalStorageHandler(new LocalStorageDriver(), $path), 16 | ]; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Services/Storage/Events/Exists/ExistsRawStorageEvent.php: -------------------------------------------------------------------------------- 1 | consumers = [ 15 | new ExistsRawLocalStorageHandler(new LocalStorageDriver(), $path), 16 | ]; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Services/Storage/Events/Get/GetEmbeddedStorageEvent.php: -------------------------------------------------------------------------------- 1 | consumers = [ 15 | new GetEmbeddedLocalStorageHandler(new LocalStorageDriver(), $path), 16 | ]; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Services/Storage/Events/Get/GetRawStorageEvent.php: -------------------------------------------------------------------------------- 1 | consumers = [ 15 | new GetRawLocalStorageHandler(new LocalStorageDriver(), $path), 16 | ]; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Services/Storage/Events/Path/PathEmbeddedStorageEvent.php: -------------------------------------------------------------------------------- 1 | consumers = [ 15 | new PathEmbeddedLocalStorageHandler(new LocalStorageDriver(), $path), 16 | ]; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Services/Storage/Events/Path/PathRawStorageEvent.php: -------------------------------------------------------------------------------- 1 | consumers = [ 15 | new PathRawLocalStorageHandler(new LocalStorageDriver(), $path), 16 | ]; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Services/Storage/Events/StorageEvent.php: -------------------------------------------------------------------------------- 1 | consumers = [ 15 | new UploadEmbeddedLocalStorageHandler(new LocalStorageDriver(), $path, $file, $visibility), 16 | ]; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Services/Storage/Events/Upload/UploadRawStorageEvent.php: -------------------------------------------------------------------------------- 1 | consumers = [ 15 | new UploadRawLocalStorageHandler(new LocalStorageDriver(), $path, $file, $visibility), 16 | ]; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Services/Storage/Events/UploadStream/UploadStreamEmbeddedStorageEvent.php: -------------------------------------------------------------------------------- 1 | consumers = [ 15 | new UploadStreamEmbeddedLocalStorageHandler(new LocalStorageDriver(), $path, $sourceStream), 16 | ]; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Services/Storage/Events/UploadStream/UploadStreamRawStorageEvent.php: -------------------------------------------------------------------------------- 1 | consumers = [ 15 | new UploadStreamRawLocalStorageHandler(new LocalStorageDriver(), $path, $sourceStream), 16 | ]; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Services/Storage/Events/Url/UrlEmbeddedStorageEvent.php: -------------------------------------------------------------------------------- 1 | consumers = [ 15 | new UrlEmbeddedLocalStorageHandler(new LocalStorageDriver(), $path), 16 | ]; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Services/Storage/Events/Url/UrlRawStorageEvent.php: -------------------------------------------------------------------------------- 1 | consumers = [ 15 | new UrlRawLocalStorageHandler(new LocalStorageDriver(), $path), 16 | ]; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Services/Storage/Handlers/BaseCopyStorageHandler.php: -------------------------------------------------------------------------------- 1 | driver = $driver; 21 | $this->path = $path; 22 | $this->existedFile = $existedFile; 23 | } 24 | 25 | public function handle(): void 26 | { 27 | if ($this->check()) { 28 | $this->isCopied = $this->driver->copy($this->path, $this->existedFile); 29 | } 30 | } 31 | 32 | public function isSuccessful(): bool 33 | { 34 | return $this->isCopied; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/Services/Storage/Handlers/BaseDeleteStorageHandler.php: -------------------------------------------------------------------------------- 1 | driver = $driver; 21 | $this->path = $path; 22 | } 23 | 24 | public function handle(): void 25 | { 26 | if ($this->check()) { 27 | $this->isDeleted = $this->driver->delete($this->path); 28 | } 29 | } 30 | 31 | public function isSuccessful(): bool 32 | { 33 | return $this->isDeleted; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Services/Storage/Handlers/BaseDownloadStorageHandler.php: -------------------------------------------------------------------------------- 1 | driver = $driver; 21 | $this->path = $path; 22 | $this->originalName = $originalName; 23 | } 24 | 25 | public function handle(): void 26 | { 27 | if ($this->check()) { 28 | $this->result = $this->driver->download($this->path, $this->originalName); 29 | } 30 | } 31 | 32 | public function getResult(): mixed 33 | { 34 | return $this->result; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/Services/Storage/Handlers/BaseExistsStorageHandler.php: -------------------------------------------------------------------------------- 1 | driver = $driver; 21 | $this->path = $path; 22 | } 23 | 24 | public function handle(): void 25 | { 26 | if ($this->check()) { 27 | $this->isExists = $this->driver->exists($this->path); 28 | } 29 | } 30 | 31 | public function isSuccessful(): bool 32 | { 33 | return $this->isExists; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Services/Storage/Handlers/BaseGetStorageHandler.php: -------------------------------------------------------------------------------- 1 | driver = $driver; 21 | $this->path = $path; 22 | } 23 | 24 | public function handle(): void 25 | { 26 | if ($this->check()) { 27 | $this->result = $this->driver->get($this->path); 28 | } 29 | } 30 | 31 | public function getResult(): string 32 | { 33 | return (string) $this->result; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Services/Storage/Handlers/BasePathStorageHandler.php: -------------------------------------------------------------------------------- 1 | driver = $driver; 21 | $this->path = $path; 22 | } 23 | 24 | public function handle(): void 25 | { 26 | if ($this->check()) { 27 | $this->result = $this->driver->path($this->path); 28 | } 29 | } 30 | 31 | public function getResult(): string 32 | { 33 | return (string) $this->result; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Services/Storage/Handlers/BaseUploadStorageHandler.php: -------------------------------------------------------------------------------- 1 | check()) { 25 | $this->isUploaded = $this->driver->upload($this->path, $this->file, $this->visibility); 26 | } 27 | } 28 | 29 | public function isSuccessful(): bool 30 | { 31 | return $this->isUploaded; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/Services/Storage/Handlers/BaseUploadStreamStorageHandler.php: -------------------------------------------------------------------------------- 1 | driver = $driver; 21 | $this->path = $path; 22 | $this->sourceStream = $sourceStream; 23 | } 24 | 25 | public function handle(): void 26 | { 27 | if ($this->check()) { 28 | $this->driver->uploadFromStream($this->path, $this->sourceStream); 29 | } 30 | } 31 | 32 | public function isSuccessful(): bool 33 | { 34 | return true; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/Services/Storage/Handlers/BaseUrlStorageHandler.php: -------------------------------------------------------------------------------- 1 | driver = $driver; 21 | $this->path = $path; 22 | } 23 | 24 | public function handle(): void 25 | { 26 | if ($this->check()) { 27 | $this->result = $this->driver->url($this->path); 28 | } 29 | } 30 | 31 | public function getResult(): string 32 | { 33 | return (string) $this->result; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Services/Storage/Handlers/Copy/CopyEmbeddedLocalStorageHandler.php: -------------------------------------------------------------------------------- 1 | make(Illuminate\Contracts\Console\Kernel::class); 34 | 35 | $status = $kernel->handle( 36 | $input = new Symfony\Component\Console\Input\ArgvInput, 37 | new Symfony\Component\Console\Output\ConsoleOutput 38 | ); 39 | 40 | /* 41 | |-------------------------------------------------------------------------- 42 | | Shutdown The Application 43 | |-------------------------------------------------------------------------- 44 | | 45 | | Once Artisan has finished running, we will fire off the shutdown events 46 | | so that any final work may be done by the application before we shut 47 | | down the process. This is the last thing to happen to the request. 48 | | 49 | */ 50 | 51 | $kernel->terminate($input, $status); 52 | 53 | exit($status); 54 | -------------------------------------------------------------------------------- /bootstrap/app.php: -------------------------------------------------------------------------------- 1 | singleton( 30 | Illuminate\Contracts\Http\Kernel::class, 31 | App\Http\Kernel::class 32 | ); 33 | 34 | $app->singleton( 35 | Illuminate\Contracts\Console\Kernel::class, 36 | App\Console\Kernel::class 37 | ); 38 | 39 | $app->singleton( 40 | Illuminate\Contracts\Debug\ExceptionHandler::class, 41 | App\Exceptions\Handler::class 42 | ); 43 | 44 | /* 45 | |-------------------------------------------------------------------------- 46 | | Return The Application 47 | |-------------------------------------------------------------------------- 48 | | 49 | | This script returns the application instance. The instance is given to 50 | | the calling script so we can separate the building of the instances 51 | | from the actual running of the application and sending responses. 52 | | 53 | */ 54 | 55 | return $app; 56 | -------------------------------------------------------------------------------- /bootstrap/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "laravel/laravel", 3 | "type": "project", 4 | "description": "The Laravel Framework.", 5 | "keywords": ["framework", "laravel"], 6 | "license": "MIT", 7 | "require": { 8 | "php": "^8.1", 9 | "guzzlehttp/guzzle": "^7.2", 10 | "laravel/framework": "^10.10", 11 | "laravel/sanctum": "^3.2", 12 | "laravel/tinker": "^2.8", 13 | "laravel/ui": "^4.2", 14 | "openai-php/client": "^0.3.5", 15 | "smalot/pdfparser": "^2.5" 16 | }, 17 | "require-dev": { 18 | "fakerphp/faker": "^1.9.1", 19 | "laravel/pint": "^1.0", 20 | "laravel/sail": "^1.18", 21 | "mockery/mockery": "^1.4.4", 22 | "nunomaduro/collision": "^7.0", 23 | "phpunit/phpunit": "^10.1", 24 | "spatie/laravel-ignition": "^2.0" 25 | }, 26 | "autoload": { 27 | "psr-4": { 28 | "App\\": "app/", 29 | "Database\\Factories\\": "database/factories/", 30 | "Database\\Seeders\\": "database/seeders/" 31 | } 32 | }, 33 | "autoload-dev": { 34 | "psr-4": { 35 | "Tests\\": "tests/" 36 | } 37 | }, 38 | "scripts": { 39 | "post-autoload-dump": [ 40 | "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", 41 | "@php artisan package:discover --ansi" 42 | ], 43 | "post-update-cmd": [ 44 | "@php artisan vendor:publish --tag=laravel-assets --ansi --force" 45 | ], 46 | "post-root-package-install": [ 47 | "@php -r \"file_exists('.env') || copy('.env.example', '.env');\"" 48 | ], 49 | "post-create-project-cmd": [ 50 | "@php artisan key:generate --ansi" 51 | ] 52 | }, 53 | "extra": { 54 | "laravel": { 55 | "dont-discover": [] 56 | } 57 | }, 58 | "config": { 59 | "optimize-autoloader": true, 60 | "preferred-install": "dist", 61 | "sort-packages": true, 62 | "allow-plugins": { 63 | "pestphp/pest-plugin": true, 64 | "php-http/discovery": true 65 | } 66 | }, 67 | "minimum-stability": "stable", 68 | "prefer-stable": true 69 | } 70 | -------------------------------------------------------------------------------- /composer.phar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IngestAI/embedditor/d3ad3603277fb936767745d0e25af6409ddf5c91/composer.phar -------------------------------------------------------------------------------- /config/auth.php: -------------------------------------------------------------------------------- 1 | [ 17 | 'guard' => 'web', 18 | 'passwords' => 'users', 19 | ], 20 | 21 | /* 22 | |-------------------------------------------------------------------------- 23 | | Authentication Guards 24 | |-------------------------------------------------------------------------- 25 | | 26 | | Next, you may define every authentication guard for your application. 27 | | Of course, a great default configuration has been defined for you 28 | | here which uses session storage and the Eloquent user provider. 29 | | 30 | | All authentication drivers have a user provider. This defines how the 31 | | users are actually retrieved out of your database or other storage 32 | | mechanisms used by this application to persist your user's data. 33 | | 34 | | Supported: "session" 35 | | 36 | */ 37 | 38 | 'guards' => [ 39 | 'web' => [ 40 | 'driver' => 'session', 41 | 'provider' => 'users', 42 | ], 43 | ], 44 | 45 | /* 46 | |-------------------------------------------------------------------------- 47 | | User Providers 48 | |-------------------------------------------------------------------------- 49 | | 50 | | All authentication drivers have a user provider. This defines how the 51 | | users are actually retrieved out of your database or other storage 52 | | mechanisms used by this application to persist your user's data. 53 | | 54 | | If you have multiple user tables or models you may configure multiple 55 | | sources which represent each model / table. These sources may then 56 | | be assigned to any extra authentication guards you have defined. 57 | | 58 | | Supported: "database", "eloquent" 59 | | 60 | */ 61 | 62 | 'providers' => [ 63 | 'users' => [ 64 | 'driver' => 'eloquent', 65 | 'model' => App\Models\User::class, 66 | ], 67 | 68 | // 'users' => [ 69 | // 'driver' => 'database', 70 | // 'table' => 'users', 71 | // ], 72 | ], 73 | 74 | /* 75 | |-------------------------------------------------------------------------- 76 | | Resetting Passwords 77 | |-------------------------------------------------------------------------- 78 | | 79 | | You may specify multiple password reset configurations if you have more 80 | | than one user table or model in the application and you want to have 81 | | separate password reset settings based on the specific user types. 82 | | 83 | | The expiry time is the number of minutes that each reset token will be 84 | | considered valid. This security feature keeps tokens short-lived so 85 | | they have less time to be guessed. You may change this as needed. 86 | | 87 | | The throttle setting is the number of seconds a user must wait before 88 | | generating more password reset tokens. This prevents the user from 89 | | quickly generating a very large amount of password reset tokens. 90 | | 91 | */ 92 | 93 | 'passwords' => [ 94 | 'users' => [ 95 | 'provider' => 'users', 96 | 'table' => 'password_reset_tokens', 97 | 'expire' => 60, 98 | 'throttle' => 60, 99 | ], 100 | ], 101 | 102 | /* 103 | |-------------------------------------------------------------------------- 104 | | Password Confirmation Timeout 105 | |-------------------------------------------------------------------------- 106 | | 107 | | Here you may define the amount of seconds before a password confirmation 108 | | times out and the user is prompted to re-enter their password via the 109 | | confirmation screen. By default, the timeout lasts for three hours. 110 | | 111 | */ 112 | 113 | 'password_timeout' => 10800, 114 | 115 | ]; 116 | -------------------------------------------------------------------------------- /config/broadcasting.php: -------------------------------------------------------------------------------- 1 | env('BROADCAST_DRIVER', 'null'), 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Broadcast Connections 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may define all of the broadcast connections that will be used 26 | | to broadcast events to other systems or over websockets. Samples of 27 | | each available type of connection are provided inside this array. 28 | | 29 | */ 30 | 31 | 'connections' => [ 32 | 33 | 'pusher' => [ 34 | 'driver' => 'pusher', 35 | 'key' => env('PUSHER_APP_KEY'), 36 | 'secret' => env('PUSHER_APP_SECRET'), 37 | 'app_id' => env('PUSHER_APP_ID'), 38 | 'options' => [ 39 | 'cluster' => env('PUSHER_APP_CLUSTER'), 40 | 'host' => env('PUSHER_HOST') ?: 'api-'.env('PUSHER_APP_CLUSTER', 'mt1').'.pusher.com', 41 | 'port' => env('PUSHER_PORT', 443), 42 | 'scheme' => env('PUSHER_SCHEME', 'https'), 43 | 'encrypted' => true, 44 | 'useTLS' => env('PUSHER_SCHEME', 'https') === 'https', 45 | ], 46 | 'client_options' => [ 47 | // Guzzle client options: https://docs.guzzlephp.org/en/stable/request-options.html 48 | ], 49 | ], 50 | 51 | 'ably' => [ 52 | 'driver' => 'ably', 53 | 'key' => env('ABLY_KEY'), 54 | ], 55 | 56 | 'redis' => [ 57 | 'driver' => 'redis', 58 | 'connection' => 'default', 59 | ], 60 | 61 | 'log' => [ 62 | 'driver' => 'log', 63 | ], 64 | 65 | 'null' => [ 66 | 'driver' => 'null', 67 | ], 68 | 69 | ], 70 | 71 | ]; 72 | -------------------------------------------------------------------------------- /config/cache.php: -------------------------------------------------------------------------------- 1 | env('CACHE_DRIVER', 'file'), 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Cache Stores 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may define all of the cache "stores" for your application as 26 | | well as their drivers. You may even define multiple stores for the 27 | | same cache driver to group types of items stored in your caches. 28 | | 29 | | Supported drivers: "apc", "array", "database", "file", 30 | | "memcached", "redis", "dynamodb", "octane", "null" 31 | | 32 | */ 33 | 34 | 'stores' => [ 35 | 36 | 'apc' => [ 37 | 'driver' => 'apc', 38 | ], 39 | 40 | 'array' => [ 41 | 'driver' => 'array', 42 | 'serialize' => false, 43 | ], 44 | 45 | 'database' => [ 46 | 'driver' => 'database', 47 | 'table' => 'cache', 48 | 'connection' => null, 49 | 'lock_connection' => null, 50 | ], 51 | 52 | 'file' => [ 53 | 'driver' => 'file', 54 | 'path' => storage_path('framework/cache/data'), 55 | ], 56 | 57 | 'memcached' => [ 58 | 'driver' => 'memcached', 59 | 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'), 60 | 'sasl' => [ 61 | env('MEMCACHED_USERNAME'), 62 | env('MEMCACHED_PASSWORD'), 63 | ], 64 | 'options' => [ 65 | // Memcached::OPT_CONNECT_TIMEOUT => 2000, 66 | ], 67 | 'servers' => [ 68 | [ 69 | 'host' => env('MEMCACHED_HOST', '127.0.0.1'), 70 | 'port' => env('MEMCACHED_PORT', 11211), 71 | 'weight' => 100, 72 | ], 73 | ], 74 | ], 75 | 76 | 'redis' => [ 77 | 'driver' => 'redis', 78 | 'connection' => 'cache', 79 | 'lock_connection' => 'default', 80 | ], 81 | 82 | 'dynamodb' => [ 83 | 'driver' => 'dynamodb', 84 | 'key' => env('AWS_ACCESS_KEY_ID'), 85 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 86 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 87 | 'table' => env('DYNAMODB_CACHE_TABLE', 'cache'), 88 | 'endpoint' => env('DYNAMODB_ENDPOINT'), 89 | ], 90 | 91 | 'octane' => [ 92 | 'driver' => 'octane', 93 | ], 94 | 95 | ], 96 | 97 | /* 98 | |-------------------------------------------------------------------------- 99 | | Cache Key Prefix 100 | |-------------------------------------------------------------------------- 101 | | 102 | | When utilizing the APC, database, memcached, Redis, or DynamoDB cache 103 | | stores there might be other applications using the same cache. For 104 | | that reason, you may prefix every cache key to avoid collisions. 105 | | 106 | */ 107 | 108 | 'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache_'), 109 | 110 | ]; 111 | -------------------------------------------------------------------------------- /config/cors.php: -------------------------------------------------------------------------------- 1 | ['api/*', 'sanctum/csrf-cookie'], 19 | 20 | 'allowed_methods' => ['*'], 21 | 22 | 'allowed_origins' => ['*'], 23 | 24 | 'allowed_origins_patterns' => [], 25 | 26 | 'allowed_headers' => ['*'], 27 | 28 | 'exposed_headers' => [], 29 | 30 | 'max_age' => 0, 31 | 32 | 'supports_credentials' => false, 33 | 34 | ]; 35 | -------------------------------------------------------------------------------- /config/filesystems.php: -------------------------------------------------------------------------------- 1 | env('FILESYSTEM_DISK', 'local'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Filesystem Disks 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Here you may configure as many filesystem "disks" as you wish, and you 24 | | may even configure multiple disks of the same driver. Defaults have 25 | | been set up for each driver as an example of the required values. 26 | | 27 | | Supported Drivers: "local", "ftp", "sftp", "s3" 28 | | 29 | */ 30 | 31 | 'disks' => [ 32 | 33 | 'local' => [ 34 | 'driver' => 'local', 35 | 'root' => storage_path('app'), 36 | 'throw' => false, 37 | 'permissions' => [ 38 | 'file' => [ 39 | 'public' => 0644, 40 | 'private' => 0600, 41 | ], 42 | 'dir' => [ 43 | 'public' => 0755, 44 | 'private' => 0700, 45 | ], 46 | ], 47 | ], 48 | 49 | 'public' => [ 50 | 'driver' => 'local', 51 | 'root' => storage_path('app/public'), 52 | 'url' => env('APP_URL').'/storage', 53 | 'visibility' => 'public', 54 | 'throw' => false, 55 | ], 56 | 57 | 's3' => [ 58 | 'driver' => 's3', 59 | 'key' => env('AWS_ACCESS_KEY_ID'), 60 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 61 | 'region' => env('AWS_DEFAULT_REGION'), 62 | 'bucket' => env('AWS_BUCKET'), 63 | 'url' => env('AWS_URL'), 64 | 'endpoint' => env('AWS_ENDPOINT'), 65 | 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), 66 | 'throw' => false, 67 | ], 68 | 69 | ], 70 | 71 | /* 72 | |-------------------------------------------------------------------------- 73 | | Symbolic Links 74 | |-------------------------------------------------------------------------- 75 | | 76 | | Here you may configure the symbolic links that will be created when the 77 | | `storage:link` Artisan command is executed. The array keys should be 78 | | the locations of the links and the values should be their targets. 79 | | 80 | */ 81 | 82 | 'links' => [ 83 | public_path('storage') => storage_path('app/public'), 84 | ], 85 | 86 | ]; 87 | -------------------------------------------------------------------------------- /config/hashing.php: -------------------------------------------------------------------------------- 1 | 'bcrypt', 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Bcrypt Options 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may specify the configuration options that should be used when 26 | | passwords are hashed using the Bcrypt algorithm. This will allow you 27 | | to control the amount of time it takes to hash the given password. 28 | | 29 | */ 30 | 31 | 'bcrypt' => [ 32 | 'rounds' => env('BCRYPT_ROUNDS', 10), 33 | ], 34 | 35 | /* 36 | |-------------------------------------------------------------------------- 37 | | Argon Options 38 | |-------------------------------------------------------------------------- 39 | | 40 | | Here you may specify the configuration options that should be used when 41 | | passwords are hashed using the Argon algorithm. These will allow you 42 | | to control the amount of time it takes to hash the given password. 43 | | 44 | */ 45 | 46 | 'argon' => [ 47 | 'memory' => 65536, 48 | 'threads' => 1, 49 | 'time' => 4, 50 | ], 51 | 52 | ]; 53 | -------------------------------------------------------------------------------- /config/mail.php: -------------------------------------------------------------------------------- 1 | env('MAIL_MAILER', 'smtp'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Mailer Configurations 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Here you may configure all of the mailers used by your application plus 24 | | their respective settings. Several examples have been configured for 25 | | you and you are free to add your own as your application requires. 26 | | 27 | | Laravel supports a variety of mail "transport" drivers to be used while 28 | | sending an e-mail. You will specify which one you are using for your 29 | | mailers below. You are free to add additional mailers as required. 30 | | 31 | | Supported: "smtp", "sendmail", "mailgun", "ses", "ses-v2", 32 | | "postmark", "log", "array", "failover" 33 | | 34 | */ 35 | 36 | 'mailers' => [ 37 | 'smtp' => [ 38 | 'transport' => 'smtp', 39 | 'url' => env('MAIL_URL'), 40 | 'host' => env('MAIL_HOST', 'smtp.mailgun.org'), 41 | 'port' => env('MAIL_PORT', 587), 42 | 'encryption' => env('MAIL_ENCRYPTION', 'tls'), 43 | 'username' => env('MAIL_USERNAME'), 44 | 'password' => env('MAIL_PASSWORD'), 45 | 'timeout' => null, 46 | 'local_domain' => env('MAIL_EHLO_DOMAIN'), 47 | ], 48 | 49 | 'ses' => [ 50 | 'transport' => 'ses', 51 | ], 52 | 53 | 'mailgun' => [ 54 | 'transport' => 'mailgun', 55 | // 'client' => [ 56 | // 'timeout' => 5, 57 | // ], 58 | ], 59 | 60 | 'postmark' => [ 61 | 'transport' => 'postmark', 62 | // 'client' => [ 63 | // 'timeout' => 5, 64 | // ], 65 | ], 66 | 67 | 'sendmail' => [ 68 | 'transport' => 'sendmail', 69 | 'path' => env('MAIL_SENDMAIL_PATH', '/usr/sbin/sendmail -bs -i'), 70 | ], 71 | 72 | 'log' => [ 73 | 'transport' => 'log', 74 | 'channel' => env('MAIL_LOG_CHANNEL'), 75 | ], 76 | 77 | 'array' => [ 78 | 'transport' => 'array', 79 | ], 80 | 81 | 'failover' => [ 82 | 'transport' => 'failover', 83 | 'mailers' => [ 84 | 'smtp', 85 | 'log', 86 | ], 87 | ], 88 | ], 89 | 90 | /* 91 | |-------------------------------------------------------------------------- 92 | | Global "From" Address 93 | |-------------------------------------------------------------------------- 94 | | 95 | | You may wish for all e-mails sent by your application to be sent from 96 | | the same address. Here, you may specify a name and address that is 97 | | used globally for all e-mails that are sent by your application. 98 | | 99 | */ 100 | 101 | 'from' => [ 102 | 'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'), 103 | 'name' => env('MAIL_FROM_NAME', 'Example'), 104 | ], 105 | 106 | /* 107 | |-------------------------------------------------------------------------- 108 | | Markdown Mail Settings 109 | |-------------------------------------------------------------------------- 110 | | 111 | | If you are using Markdown based email rendering, you may configure your 112 | | theme and component paths here, allowing you to customize the design 113 | | of the emails. Or, you may simply stick with the Laravel defaults! 114 | | 115 | */ 116 | 117 | 'markdown' => [ 118 | 'theme' => 'default', 119 | 120 | 'paths' => [ 121 | resource_path('views/vendor/mail'), 122 | ], 123 | ], 124 | 125 | ]; 126 | -------------------------------------------------------------------------------- /config/queue.php: -------------------------------------------------------------------------------- 1 | env('QUEUE_CONNECTION', 'sync'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Queue Connections 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Here you may configure the connection information for each server that 24 | | is used by your application. A default configuration has been added 25 | | for each back-end shipped with Laravel. You are free to add more. 26 | | 27 | | Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null" 28 | | 29 | */ 30 | 31 | 'connections' => [ 32 | 33 | 'sync' => [ 34 | 'driver' => 'sync', 35 | ], 36 | 37 | 'database' => [ 38 | 'driver' => 'database', 39 | 'table' => 'jobs', 40 | 'queue' => 'default', 41 | 'retry_after' => 90, 42 | 'after_commit' => false, 43 | ], 44 | 45 | 'beanstalkd' => [ 46 | 'driver' => 'beanstalkd', 47 | 'host' => 'localhost', 48 | 'queue' => 'default', 49 | 'retry_after' => 90, 50 | 'block_for' => 0, 51 | 'after_commit' => false, 52 | ], 53 | 54 | 'sqs' => [ 55 | 'driver' => 'sqs', 56 | 'key' => env('AWS_ACCESS_KEY_ID'), 57 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 58 | 'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'), 59 | 'queue' => env('SQS_QUEUE', 'default'), 60 | 'suffix' => env('SQS_SUFFIX'), 61 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 62 | 'after_commit' => false, 63 | ], 64 | 65 | 'redis' => [ 66 | 'driver' => 'redis', 67 | 'connection' => 'default', 68 | 'queue' => env('REDIS_QUEUE', 'default'), 69 | 'retry_after' => 90, 70 | 'block_for' => null, 71 | 'after_commit' => false, 72 | ], 73 | 74 | ], 75 | 76 | /* 77 | |-------------------------------------------------------------------------- 78 | | Job Batching 79 | |-------------------------------------------------------------------------- 80 | | 81 | | The following options configure the database and table that store job 82 | | batching information. These options can be updated to any database 83 | | connection and table which has been defined by your application. 84 | | 85 | */ 86 | 87 | 'batching' => [ 88 | 'database' => env('DB_CONNECTION', 'mysql'), 89 | 'table' => 'job_batches', 90 | ], 91 | 92 | /* 93 | |-------------------------------------------------------------------------- 94 | | Failed Queue Jobs 95 | |-------------------------------------------------------------------------- 96 | | 97 | | These options configure the behavior of failed queue job logging so you 98 | | can control which database and table are used to store the jobs that 99 | | have failed. You may change them to any database / table you wish. 100 | | 101 | */ 102 | 103 | 'failed' => [ 104 | 'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'), 105 | 'database' => env('DB_CONNECTION', 'mysql'), 106 | 'table' => 'failed_jobs', 107 | ], 108 | 109 | ]; 110 | -------------------------------------------------------------------------------- /config/sanctum.php: -------------------------------------------------------------------------------- 1 | explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf( 19 | '%s%s', 20 | 'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1', 21 | Sanctum::currentApplicationUrlWithPort() 22 | ))), 23 | 24 | /* 25 | |-------------------------------------------------------------------------- 26 | | Sanctum Guards 27 | |-------------------------------------------------------------------------- 28 | | 29 | | This array contains the authentication guards that will be checked when 30 | | Sanctum is trying to authenticate a request. If none of these guards 31 | | are able to authenticate the request, Sanctum will use the bearer 32 | | token that's present on an incoming request for authentication. 33 | | 34 | */ 35 | 36 | 'guard' => ['web'], 37 | 38 | /* 39 | |-------------------------------------------------------------------------- 40 | | Expiration Minutes 41 | |-------------------------------------------------------------------------- 42 | | 43 | | This value controls the number of minutes until an issued token will be 44 | | considered expired. If this value is null, personal access tokens do 45 | | not expire. This won't tweak the lifetime of first-party sessions. 46 | | 47 | */ 48 | 49 | 'expiration' => null, 50 | 51 | /* 52 | |-------------------------------------------------------------------------- 53 | | Sanctum Middleware 54 | |-------------------------------------------------------------------------- 55 | | 56 | | When authenticating your first-party SPA with Sanctum you may need to 57 | | customize some of the middleware Sanctum uses while processing the 58 | | request. You may change the middleware listed below as required. 59 | | 60 | */ 61 | 62 | 'middleware' => [ 63 | 'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class, 64 | 'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class, 65 | ], 66 | 67 | ]; 68 | -------------------------------------------------------------------------------- /config/services.php: -------------------------------------------------------------------------------- 1 | [ 18 | 'domain' => env('MAILGUN_DOMAIN'), 19 | 'secret' => env('MAILGUN_SECRET'), 20 | 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'), 21 | 'scheme' => 'https', 22 | ], 23 | 24 | 'postmark' => [ 25 | 'token' => env('POSTMARK_TOKEN'), 26 | ], 27 | 28 | 'ses' => [ 29 | 'key' => env('AWS_ACCESS_KEY_ID'), 30 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 31 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 32 | ], 33 | 34 | 'ai' => [ 35 | 'embedding' => 'openai', 36 | 'completion' => 'openai', 37 | ], 38 | 39 | 'openai' => [ 40 | 'api_key' => env('OPENAI_API_KEY', ''), 41 | ], 42 | 43 | ]; 44 | -------------------------------------------------------------------------------- /config/view.php: -------------------------------------------------------------------------------- 1 | [ 17 | resource_path('views'), 18 | ], 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Compiled View Path 23 | |-------------------------------------------------------------------------- 24 | | 25 | | This option determines where all the compiled Blade templates will be 26 | | stored for your application. Typically, this is within the storage 27 | | directory. However, as usual, you are free to change this value. 28 | | 29 | */ 30 | 31 | 'compiled' => env( 32 | 'VIEW_COMPILED_PATH', 33 | realpath(storage_path('framework/views')) 34 | ), 35 | 36 | ]; 37 | -------------------------------------------------------------------------------- /database/.gitignore: -------------------------------------------------------------------------------- 1 | *.sqlite* 2 | -------------------------------------------------------------------------------- /database/factories/UserFactory.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class UserFactory extends Factory 12 | { 13 | /** 14 | * Define the model's default state. 15 | * 16 | * @return array 17 | */ 18 | public function definition(): array 19 | { 20 | return [ 21 | 'name' => fake()->name(), 22 | 'email' => fake()->unique()->safeEmail(), 23 | 'email_verified_at' => now(), 24 | 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password 25 | 'remember_token' => Str::random(10), 26 | ]; 27 | } 28 | 29 | /** 30 | * Indicate that the model's email address should be unverified. 31 | */ 32 | public function unverified(): static 33 | { 34 | return $this->state(fn (array $attributes) => [ 35 | 'email_verified_at' => null, 36 | ]); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /database/migrations/2014_10_12_000000_create_users_table.php: -------------------------------------------------------------------------------- 1 | id(); 16 | $table->string('name'); 17 | $table->string('email')->unique(); 18 | $table->timestamp('email_verified_at')->nullable(); 19 | $table->string('password'); 20 | $table->rememberToken(); 21 | $table->timestamps(); 22 | }); 23 | } 24 | 25 | /** 26 | * Reverse the migrations. 27 | */ 28 | public function down(): void 29 | { 30 | Schema::dropIfExists('users'); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /database/migrations/2014_10_12_100000_create_password_reset_tokens_table.php: -------------------------------------------------------------------------------- 1 | string('email')->primary(); 16 | $table->string('token'); 17 | $table->timestamp('created_at')->nullable(); 18 | }); 19 | } 20 | 21 | /** 22 | * Reverse the migrations. 23 | */ 24 | public function down(): void 25 | { 26 | Schema::dropIfExists('password_reset_tokens'); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /database/migrations/2019_08_19_000000_create_failed_jobs_table.php: -------------------------------------------------------------------------------- 1 | id(); 16 | $table->string('uuid')->unique(); 17 | $table->text('connection'); 18 | $table->text('queue'); 19 | $table->longText('payload'); 20 | $table->longText('exception'); 21 | $table->timestamp('failed_at')->useCurrent(); 22 | }); 23 | } 24 | 25 | /** 26 | * Reverse the migrations. 27 | */ 28 | public function down(): void 29 | { 30 | Schema::dropIfExists('failed_jobs'); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php: -------------------------------------------------------------------------------- 1 | id(); 16 | $table->morphs('tokenable'); 17 | $table->string('name'); 18 | $table->string('token', 64)->unique(); 19 | $table->text('abilities')->nullable(); 20 | $table->timestamp('last_used_at')->nullable(); 21 | $table->timestamp('expires_at')->nullable(); 22 | $table->timestamps(); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | */ 29 | public function down(): void 30 | { 31 | Schema::dropIfExists('personal_access_tokens'); 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /database/migrations/2023_05_19_180101_create_libraries_table.php: -------------------------------------------------------------------------------- 1 | id(); 16 | $table->string('name', 191)->index()->nullable(); 17 | $table->decimal('temperature', 5)->nullable(); 18 | $table->unsignedInteger('chunk_size'); 19 | $table->timestamps(); 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | */ 26 | public function down(): void 27 | { 28 | Schema::dropIfExists('libraries'); 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /database/migrations/2023_05_20_081521_create_library_files_table.php: -------------------------------------------------------------------------------- 1 | id(); 16 | $table->unsignedBigInteger('library_id'); 17 | $table->string('original_name'); 18 | $table->string('filename'); 19 | $table->string('file_key'); 20 | $table->boolean('uploaded')->default(false); 21 | $table->boolean('formatted')->default(false); 22 | $table->boolean('embedded')->default(false); 23 | $table->timestamps(); 24 | 25 | 26 | $table->foreign('library_id', 'fk_library') 27 | ->references('id') 28 | ->on('libraries') 29 | ->onDelete('cascade') 30 | ->onUpdate('cascade'); 31 | 32 | }); 33 | } 34 | 35 | /** 36 | * Reverse the migrations. 37 | */ 38 | public function down(): void 39 | { 40 | Schema::dropIfExists('library_files'); 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /database/migrations/2023_05_20_184919_add_chunk_separator_to_libraries_table.php: -------------------------------------------------------------------------------- 1 | string('chunk_separator', 255)->nullable()->after('chunk_size'); 16 | }); 17 | } 18 | 19 | /** 20 | * Reverse the migrations. 21 | */ 22 | public function down(): void 23 | { 24 | Schema::table('libraries', function (Blueprint $table) { 25 | $table->dropColumn('chunk_separator'); 26 | }); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /database/migrations/2023_05_20_185027_add_chunked_list_library_file_table.php: -------------------------------------------------------------------------------- 1 | json('chunked_list')->nullable()->after('embedded'); 16 | $table->tinyInteger('chunked')->index()->unsigned()->default(0)->after('embedded'); 17 | }); 18 | } 19 | 20 | /** 21 | * Reverse the migrations. 22 | */ 23 | public function down(): void 24 | { 25 | Schema::table('library_files', function (Blueprint $table) { 26 | $table->dropColumn('chunked_list'); 27 | }); 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /database/migrations/2023_05_20_194118_add_embedded_model_into_library.php: -------------------------------------------------------------------------------- 1 | string('embedded_model')->default('text-embedding-ada-002')->after('name'); 16 | }); 17 | } 18 | 19 | /** 20 | * Reverse the migrations. 21 | */ 22 | public function down(): void 23 | { 24 | Schema::table('libraries', function ($table) { 25 | $table->dropColumn('embedded_model'); 26 | }); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /database/migrations/2023_05_21_083644_create_providers_table.php: -------------------------------------------------------------------------------- 1 | id(); 16 | $table->string('slug')->unique(); 17 | $table->string('name'); 18 | $table->boolean('active')->default(false); 19 | $table->timestamps(); 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | */ 26 | public function down(): void 27 | { 28 | Schema::dropIfExists('providers'); 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /database/migrations/2023_05_21_084107_create_provider_models_table.php: -------------------------------------------------------------------------------- 1 | id(); 16 | $table->unsignedBigInteger('provider_id'); 17 | $table->string('slug')->unique()->nullable(); 18 | $table->string('name')->index()->nullable(); 19 | $table->boolean('active')->default(false); 20 | $table->string('input_format')->index()->nullable(); 21 | $table->string('output_format')->index()->nullable(); 22 | $table->timestamps(); 23 | 24 | $table->foreign('provider_id', 'fk_provider_model') 25 | ->references('id') 26 | ->on('providers') 27 | ->onDelete('cascade') 28 | ->onUpdate('cascade'); 29 | }); 30 | } 31 | 32 | /** 33 | * Reverse the migrations. 34 | */ 35 | public function down(): void 36 | { 37 | Schema::dropIfExists('provider_models'); 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /database/migrations/2023_05_22_123515_add_optional_fields_into_library_files.php: -------------------------------------------------------------------------------- 1 | boolean('lowercase')->default(false)->after('file_key'); 16 | $table->boolean('stop_word')->default(false)->after('lowercase'); 17 | }); 18 | } 19 | 20 | /** 21 | * Reverse the migrations. 22 | */ 23 | public function down(): void 24 | { 25 | Schema::table('library_files', function (Blueprint $table) { 26 | $table->dropColumn('lowercase'); 27 | $table->dropColumn('stop_word'); 28 | }); 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /database/migrations/2023_05_22_154003_add_strip_fields_to_library_files.php: -------------------------------------------------------------------------------- 1 | boolean('strip_tag')->default(false)->after('file_key'); 16 | $table->boolean('strip_punctuation')->default(false)->after('strip_tag'); 17 | $table->boolean('strip_special_char')->default(false)->after('strip_punctuation'); 18 | }); 19 | } 20 | 21 | /** 22 | * Reverse the migrations. 23 | */ 24 | public function down(): void 25 | { 26 | Schema::table('library_files', function (Blueprint $table) { 27 | $table->dropColumn('strip_tag'); 28 | $table->dropColumn('strip_punctuation'); 29 | $table->dropColumn('strip_special_char'); 30 | }); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /database/migrations/2023_05_23_095012_add_count_words_into_files.php: -------------------------------------------------------------------------------- 1 | unsignedBigInteger('total_words')->default(0)->after('chunked_list'); 16 | $table->unsignedBigInteger('total_embedded_words')->default(0)->after('chunked_list'); 17 | }); 18 | } 19 | 20 | /** 21 | * Reverse the migrations. 22 | */ 23 | public function down(): void 24 | { 25 | Schema::table('library_files', function (Blueprint $table) { 26 | $table->dropColumn('total_words'); 27 | $table->dropColumn('total_embedded_words'); 28 | }); 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /database/migrations/2023_11_04_150205_add_g_p_t3516_k_model_into_models.php: -------------------------------------------------------------------------------- 1 | where('slug', 'openai') 17 | ->pluck('id') 18 | ->first(); 19 | 20 | DB::table('provider_models')->insert([ 21 | [ 22 | 'provider_id' => $openaiProvider, 23 | 'slug' => 'gpt-3.5-turbo-16k', 24 | 'name' => 'GPT-3.5 16K', 25 | 'active' => true, 26 | 'input_format' => 'text', 27 | 'output_format' => 'text', 28 | ], 29 | ]); 30 | } 31 | 32 | /** 33 | * Reverse the migrations. 34 | */ 35 | public function down(): void 36 | { 37 | DB::table('provider_models') 38 | ->where('slug', 'gpt-3.5-turbo-16k') 39 | ->delete(); 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /database/seeders/DatabaseSeeder.php: -------------------------------------------------------------------------------- 1 | call([ 15 | LibrarySeeder::class, 16 | ProviderSeeder::class, 17 | ProviderModelSeeder::class, 18 | ]); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /database/seeders/LibrarySeeder.php: -------------------------------------------------------------------------------- 1 | truncate(); 17 | DB::statement('SET FOREIGN_KEY_CHECKS=1'); 18 | 19 | DB::table('libraries')->insert([ 20 | 'name' => 'Default library', 21 | 'temperature' => 0.5, 22 | 'chunk_size' => 1500, 23 | ]); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /database/seeders/ProviderModelSeeder.php: -------------------------------------------------------------------------------- 1 | pluck('id', 'slug')->toArray(); 16 | 17 | $openaiProvider = $providers['openai'] ?? null; 18 | 19 | DB::statement('SET FOREIGN_KEY_CHECKS=0'); 20 | DB::table('provider_models')->truncate(); 21 | DB::statement('SET FOREIGN_KEY_CHECKS=1'); 22 | 23 | DB::table('provider_models')->insert([ 24 | [ 25 | 'provider_id' => $openaiProvider, 26 | 'slug' => 'gpt-3.5-turbo', 27 | 'name' => 'GPT-3.5 Turbo', 28 | 'active' => true, 29 | 'input_format' => 'text', 30 | 'output_format' => 'text', 31 | ], 32 | [ 33 | 'provider_id' => $openaiProvider, 34 | 'slug' => 'gpt-4', 35 | 'name' => 'GPT-4', 36 | 'active' => true, 37 | 'input_format' => 'text', 38 | 'output_format' => 'text', 39 | ], 40 | [ 41 | 'provider_id' => $openaiProvider, 42 | 'slug' => 'text-davinci-003', 43 | 'name' => 'Text Davinci 003', 44 | 'active' => true, 45 | 'input_format' => 'text', 46 | 'output_format' => 'text', 47 | ], 48 | [ 49 | 'provider_id' => $openaiProvider, 50 | 'slug' => 'text-davinci-002', 51 | 'name' => 'Text Davinci 002', 52 | 'active' => true, 53 | 'input_format' => 'text', 54 | 'output_format' => 'text', 55 | ], 56 | [ 57 | 'provider_id' => $openaiProvider, 58 | 'slug' => 'text-curie-001', 59 | 'name' => 'Text Curie 001', 60 | 'active' => true, 61 | 'input_format' => 'text', 62 | 'output_format' => 'text', 63 | ], 64 | [ 65 | 'provider_id' => $openaiProvider, 66 | 'slug' => 'text-babbage-001', 67 | 'name' => 'Text Babbage 001', 68 | 'active' => true, 69 | 'input_format' => 'text', 70 | 'output_format' => 'text', 71 | ], 72 | [ 73 | 'provider_id' => $openaiProvider, 74 | 'slug' => 'text-ada-001', 75 | 'name' => 'Text Ada 001', 76 | 'active' => true, 77 | 'input_format' => 'text', 78 | 'output_format' => 'text', 79 | ], 80 | ]); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /database/seeders/ProviderSeeder.php: -------------------------------------------------------------------------------- 1 | truncate(); 17 | DB::statement('SET FOREIGN_KEY_CHECKS=1'); 18 | 19 | DB::table('providers')->insert([ 20 | [ 21 | 'slug' => 'openai', 22 | 'name' => 'OpenAI', 23 | 'active' => true, 24 | ], 25 | ]); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.7" 2 | services: 3 | app: 4 | build: 5 | args: 6 | user: foggy 7 | uid: 1000 8 | context: . 9 | dockerfile: Dockerfile 10 | image: embedditor 11 | container_name: embedditor-app 12 | restart: unless-stopped 13 | working_dir: /var/www/ 14 | volumes: 15 | - .:/var/www 16 | networks: 17 | - embedditor 18 | db: 19 | image: mysql:5.7 20 | container_name: embedditor-db 21 | restart: unless-stopped 22 | command: [--ignore-db-dir=lost+found] 23 | ports: 24 | - "13306:3306" 25 | environment: 26 | MYSQL_DATABASE: embedditor 27 | MYSQL_ROOT_PASSWORD: 1234 28 | SERVICE_TAGS: dev 29 | SERVICE_NAME: mysql 30 | volumes: 31 | - ./docker/mysql:/docker-entrypoint-initdb.d 32 | networks: 33 | - embedditor 34 | nginx: 35 | image: nginx:alpine 36 | container_name: embedditor-nginx 37 | restart: unless-stopped 38 | ports: 39 | - 8030:80 40 | volumes: 41 | - .:/var/www 42 | - ./docker/nginx:/etc/nginx/conf.d/ 43 | networks: 44 | - embedditor 45 | networks: 46 | embedditor: 47 | driver: bridge 48 | 49 | -------------------------------------------------------------------------------- /docker/nginx/embedditor.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | index index.php index.html; 4 | error_log /var/log/nginx/error.log; 5 | access_log /var/log/nginx/access.log; 6 | root /var/www/public; 7 | location ~ \.php$ { 8 | try_files $uri =404; 9 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 10 | fastcgi_pass app:9000; 11 | fastcgi_index index.php; 12 | include fastcgi_params; 13 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 14 | fastcgi_param PATH_INFO $fastcgi_path_info; 15 | } 16 | location / { 17 | try_files $uri $uri/ /index.php?$query_string; 18 | gzip_static on; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /docker/startup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | role=${CONTAINER_ROLE:-app} 4 | env=${APP_ENV:-production} 5 | 6 | if [ "$env" != "local" ]; then 7 | echo "Caching configuration..." 8 | cd /var/www 9 | php artisan config:cache 10 | php artisan route:cache 11 | php artisan view:cache 12 | fi 13 | 14 | if [ "$role" = "app" ]; then 15 | 16 | exec php-fpm 17 | 18 | else 19 | echo "Could not match the container role \"$role\"" 20 | exit 1 21 | fi 22 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | ./tests/Unit 10 | 11 | 12 | ./tests/Feature 13 | 14 | 15 | 16 | 17 | ./app 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /public/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | 3 | Options -MultiViews -Indexes 4 | 5 | 6 | RewriteEngine On 7 | 8 | # Handle Authorization Header 9 | RewriteCond %{HTTP:Authorization} . 10 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 11 | 12 | # Redirect Trailing Slashes If Not A Folder... 13 | RewriteCond %{REQUEST_FILENAME} !-d 14 | RewriteCond %{REQUEST_URI} (.+)/$ 15 | RewriteRule ^ %1 [L,R=301] 16 | 17 | # Send Requests To Front Controller... 18 | RewriteCond %{REQUEST_FILENAME} !-d 19 | RewriteCond %{REQUEST_FILENAME} !-f 20 | RewriteRule ^ index.php [L] 21 | 22 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IngestAI/embedditor/d3ad3603277fb936767745d0e25af6409ddf5c91/public/favicon.ico -------------------------------------------------------------------------------- /public/images/android-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IngestAI/embedditor/d3ad3603277fb936767745d0e25af6409ddf5c91/public/images/android-icon-144x144.png -------------------------------------------------------------------------------- /public/images/android-icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IngestAI/embedditor/d3ad3603277fb936767745d0e25af6409ddf5c91/public/images/android-icon-192x192.png -------------------------------------------------------------------------------- /public/images/android-icon-36x36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IngestAI/embedditor/d3ad3603277fb936767745d0e25af6409ddf5c91/public/images/android-icon-36x36.png -------------------------------------------------------------------------------- /public/images/android-icon-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IngestAI/embedditor/d3ad3603277fb936767745d0e25af6409ddf5c91/public/images/android-icon-48x48.png -------------------------------------------------------------------------------- /public/images/android-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IngestAI/embedditor/d3ad3603277fb936767745d0e25af6409ddf5c91/public/images/android-icon-72x72.png -------------------------------------------------------------------------------- /public/images/android-icon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IngestAI/embedditor/d3ad3603277fb936767745d0e25af6409ddf5c91/public/images/android-icon-96x96.png -------------------------------------------------------------------------------- /public/images/apple-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IngestAI/embedditor/d3ad3603277fb936767745d0e25af6409ddf5c91/public/images/apple-icon-114x114.png -------------------------------------------------------------------------------- /public/images/apple-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IngestAI/embedditor/d3ad3603277fb936767745d0e25af6409ddf5c91/public/images/apple-icon-120x120.png -------------------------------------------------------------------------------- /public/images/apple-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IngestAI/embedditor/d3ad3603277fb936767745d0e25af6409ddf5c91/public/images/apple-icon-144x144.png -------------------------------------------------------------------------------- /public/images/apple-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IngestAI/embedditor/d3ad3603277fb936767745d0e25af6409ddf5c91/public/images/apple-icon-152x152.png -------------------------------------------------------------------------------- /public/images/apple-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IngestAI/embedditor/d3ad3603277fb936767745d0e25af6409ddf5c91/public/images/apple-icon-180x180.png -------------------------------------------------------------------------------- /public/images/apple-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IngestAI/embedditor/d3ad3603277fb936767745d0e25af6409ddf5c91/public/images/apple-icon-57x57.png -------------------------------------------------------------------------------- /public/images/apple-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IngestAI/embedditor/d3ad3603277fb936767745d0e25af6409ddf5c91/public/images/apple-icon-60x60.png -------------------------------------------------------------------------------- /public/images/apple-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IngestAI/embedditor/d3ad3603277fb936767745d0e25af6409ddf5c91/public/images/apple-icon-72x72.png -------------------------------------------------------------------------------- /public/images/apple-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IngestAI/embedditor/d3ad3603277fb936767745d0e25af6409ddf5c91/public/images/apple-icon-76x76.png -------------------------------------------------------------------------------- /public/images/apple-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IngestAI/embedditor/d3ad3603277fb936767745d0e25af6409ddf5c91/public/images/apple-icon-precomposed.png -------------------------------------------------------------------------------- /public/images/apple-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IngestAI/embedditor/d3ad3603277fb936767745d0e25af6409ddf5c91/public/images/apple-icon.png -------------------------------------------------------------------------------- /public/images/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | #ffffff -------------------------------------------------------------------------------- /public/images/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IngestAI/embedditor/d3ad3603277fb936767745d0e25af6409ddf5c91/public/images/favicon-16x16.png -------------------------------------------------------------------------------- /public/images/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IngestAI/embedditor/d3ad3603277fb936767745d0e25af6409ddf5c91/public/images/favicon-32x32.png -------------------------------------------------------------------------------- /public/images/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IngestAI/embedditor/d3ad3603277fb936767745d0e25af6409ddf5c91/public/images/favicon-96x96.png -------------------------------------------------------------------------------- /public/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IngestAI/embedditor/d3ad3603277fb936767745d0e25af6409ddf5c91/public/images/favicon.ico -------------------------------------------------------------------------------- /public/images/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IngestAI/embedditor/d3ad3603277fb936767745d0e25af6409ddf5c91/public/images/logo.jpg -------------------------------------------------------------------------------- /public/images/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "App", 3 | "icons": [ 4 | { 5 | "src": "\/android-icon-36x36.png", 6 | "sizes": "36x36", 7 | "type": "image\/png", 8 | "density": "0.75" 9 | }, 10 | { 11 | "src": "\/android-icon-48x48.png", 12 | "sizes": "48x48", 13 | "type": "image\/png", 14 | "density": "1.0" 15 | }, 16 | { 17 | "src": "\/android-icon-72x72.png", 18 | "sizes": "72x72", 19 | "type": "image\/png", 20 | "density": "1.5" 21 | }, 22 | { 23 | "src": "\/android-icon-96x96.png", 24 | "sizes": "96x96", 25 | "type": "image\/png", 26 | "density": "2.0" 27 | }, 28 | { 29 | "src": "\/android-icon-144x144.png", 30 | "sizes": "144x144", 31 | "type": "image\/png", 32 | "density": "3.0" 33 | }, 34 | { 35 | "src": "\/android-icon-192x192.png", 36 | "sizes": "192x192", 37 | "type": "image\/png", 38 | "density": "4.0" 39 | } 40 | ] 41 | } -------------------------------------------------------------------------------- /public/images/ms-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IngestAI/embedditor/d3ad3603277fb936767745d0e25af6409ddf5c91/public/images/ms-icon-144x144.png -------------------------------------------------------------------------------- /public/images/ms-icon-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IngestAI/embedditor/d3ad3603277fb936767745d0e25af6409ddf5c91/public/images/ms-icon-150x150.png -------------------------------------------------------------------------------- /public/images/ms-icon-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IngestAI/embedditor/d3ad3603277fb936767745d0e25af6409ddf5c91/public/images/ms-icon-310x310.png -------------------------------------------------------------------------------- /public/images/ms-icon-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IngestAI/embedditor/d3ad3603277fb936767745d0e25af6409ddf5c91/public/images/ms-icon-70x70.png -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | make(Kernel::class); 50 | 51 | $response = $kernel->handle( 52 | $request = Request::capture() 53 | )->send(); 54 | 55 | $kernel->terminate($request, $response); 56 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /resources/views/layouts/app.blade.php: -------------------------------------------------------------------------------- 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 | {{ config('app.name', 'Embedditor') }} 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | @yield('css') 37 | 38 | 39 |
40 | 50 | 51 |
52 | @yield('content') 53 |
54 | 55 |
56 |
57 |

© . IngestAI Labs Inc.

58 |
59 |
60 |
61 | 62 | 63 | 64 | 65 | @yield('js') 66 | 67 | 68 | -------------------------------------------------------------------------------- /routes/api.php: -------------------------------------------------------------------------------- 1 | get('/user', function (Request $request) { 18 | return $request->user(); 19 | }); 20 | -------------------------------------------------------------------------------- /routes/channels.php: -------------------------------------------------------------------------------- 1 | id === (int) $id; 18 | }); 19 | -------------------------------------------------------------------------------- /routes/console.php: -------------------------------------------------------------------------------- 1 | comment(Inspiring::quote()); 19 | })->purpose('Display an inspiring quote'); 20 | -------------------------------------------------------------------------------- /routes/web.php: -------------------------------------------------------------------------------- 1 | name('web::library::index'); 21 | 22 | Route::post('/save', [LibraryController::class, 'save'])->name('web::library::save'); 23 | 24 | Route::group(['prefix' => '/file'], function () { 25 | Route::post('/upload', [FileController::class, 'upload'])->name('web::file::upload'); 26 | Route::get('/download/{key}', [FileController::class, 'download'])->name('web::file::download'); 27 | Route::get('/view/{library_file}', [FileController::class, 'view'])->name('web::file::view'); 28 | Route::get('/delete/{library_file}', [FileController::class, 'delete'])->name('web::file::delete'); 29 | Route::get('/chunks/{library_file}', [FileController::class, 'chunks'])->name('web::file::chunks'); 30 | 31 | Route::get('/chunks/edit/{library_file}', [FileEditorController::class, 'chunksEdit'])->name('web::file::chunks::edit'); 32 | Route::put('/chunks/edit/{library_file}', [FileEditorController::class, 'chunksUpdate'])->name('web::file::chunks::update'); 33 | }); 34 | 35 | Route::group(['prefix' => '/playground'], function () { 36 | Route::get('/form', [PlaygroundController::class, 'index'])->name('web::playground::form'); 37 | Route::post('/send', [PlaygroundController::class, 'send'])->name('web::playground::send'); 38 | }); 39 | -------------------------------------------------------------------------------- /storage/app/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !public/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /storage/app/public/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/.gitignore: -------------------------------------------------------------------------------- 1 | compiled.php 2 | config.php 3 | down 4 | events.scanned.php 5 | maintenance.php 6 | routes.php 7 | routes.scanned.php 8 | schedule-* 9 | services.json 10 | -------------------------------------------------------------------------------- /storage/framework/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !data/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /storage/framework/cache/data/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/sessions/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/testing/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/views/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /tests/CreatesApplication.php: -------------------------------------------------------------------------------- 1 | make(Kernel::class)->bootstrap(); 18 | 19 | return $app; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tests/Feature/ExampleTest.php: -------------------------------------------------------------------------------- 1 | get('/'); 16 | 17 | $response->assertStatus(200); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/TestCase.php: -------------------------------------------------------------------------------- 1 | assertTrue(true); 15 | } 16 | } 17 | --------------------------------------------------------------------------------