diff --git a/.env.example b/.env.example index b574c76..abce85b 100644 --- a/.env.example +++ b/.env.example @@ -1,24 +1,12 @@ -APP_NAME=Laravel +APP_NAME=Amber APP_ENV=local APP_KEY= APP_DEBUG=true -APP_TIMEZONE=UTC +APP_TIMEZONE=PRC APP_URL=http://localhost -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US - -APP_MAINTENANCE_DRIVER=file -# APP_MAINTENANCE_STORE=database - BCRYPT_ROUNDS=12 -LOG_CHANNEL=stack -LOG_STACK=single -LOG_DEPRECATIONS_CHANNEL=null -LOG_LEVEL=debug - DB_CONNECTION=pgsql DB_HOST=127.0.0.1 DB_PORT=5432 @@ -26,27 +14,12 @@ DB_DATABASE=amber DB_USERNAME=root DB_PASSWORD= -SESSION_DRIVER=database -SESSION_LIFETIME=120 -SESSION_ENCRYPT=false -SESSION_PATH=/ -SESSION_DOMAIN=null - -BROADCAST_CONNECTION=log -FILESYSTEM_DISK=local -QUEUE_CONNECTION=database - -CACHE_STORE=database -CACHE_PREFIX= - -MEMCACHED_HOST=127.0.0.1 - REDIS_CLIENT=phpredis REDIS_HOST=127.0.0.1 REDIS_PASSWORD=null REDIS_PORT=6379 -MAIL_MAILER=log +MAIL_MAILER=smtp MAIL_HOST=127.0.0.1 MAIL_PORT=2525 MAIL_USERNAME=null @@ -59,7 +32,6 @@ AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= AWS_DEFAULT_REGION=us-east-1 AWS_BUCKET= -AWS_USE_PATH_STYLE_ENDPOINT=false VITE_APP_NAME="${APP_NAME}" diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..cebb43f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,40 @@ +FROM registry.leafdev.top/leaf/docker-php-image:8.3 + +WORKDIR /app + +COPY . /app +COPY start.sh /usr/bin/start.sh + +RUN useradd -ms /bin/bash -u 1337 www && chown -R 1337:1337 /app && chmod +x /usr/bin/start.sh + +# Switch to non-root user +USER www + + +# unset composer repo +RUN composer config -g repo.packagist composer https://packagist.org && \ + rm -rf ~/.composer/cache && \ + rm -rf .env && \ + php init.php && rm init.php && \ + composer install --no-dev && \ + composer dump-autoload --optimize --no-dev --classmap-authoritative && \ + composer clear-cache && \ + art view:cache && \ + ./vendor/bin/rr get-binary && \ + art octane:install --server=roadrunner + + +# COPY deploy/start-container /usr/local/bin/start-container +# COPY deploy/supervisord.conf /etc/supervisor/conf.d/supervisord.conf +# COPY vendor /app/vendor +# RUN chmod +x /usr/local/bin/start-container + +EXPOSE 8000 + +# ENTRYPOINT ["start-container"] +# Start Web +# CMD [ "/usr/bin/php", "/app/artisan", "app:init", "--start" ] +CMD [ "/usr/bin/php", "/app/artisan", "octane:start", "--server=roadrunner", "--host=0.0.0.0", "--workers=1" ] + +# Start queue +# CMD [ "/usr/bin/php", "/app/artisan", "init", "queue", "--tries=3", "--timeout=60" ] diff --git a/app/Console/Commands/InitCommand.php b/app/Console/Commands/InitCommand.php new file mode 100644 index 0000000..0450222 --- /dev/null +++ b/app/Console/Commands/InitCommand.php @@ -0,0 +1,60 @@ +call('optimize'); + + $type = $this->argument('type'); + + if ($type === 'web') { + $this->info('启动 Web 服务。'); + $this->startWeb(); + } else { + $this->info('启动队列服务。'); + $this->startQueue(); + } + + return 0; + } + + public function startWeb(): void + { + $this->call('octane:start', [ + '--server' => $this->option('server'), + '--host' => $this->option('host'), + '--port' => $this->option('port'), + '--workers' => $this->option('workers'), + ]); + } + + public function startQueue(): void + { + $this->call('queue:work', [ + '--queue' => $this->option('queue'), + '--name' => $this->option('name'), + ]); + } +} diff --git a/app/LLM/BaseLLM.php b/app/LLM/BaseLLM.php index 046fa67..3faa672 100644 --- a/app/LLM/BaseLLM.php +++ b/app/LLM/BaseLLM.php @@ -11,6 +11,7 @@ interface BaseLLM public function setHistory(History $history); public function setTools(Collection $tools); + public function setUser(User $user); public function streamResponse(); diff --git a/app/LLM/Qwen.php b/app/LLM/Qwen.php index 63fa14d..4b79f2e 100644 --- a/app/LLM/Qwen.php +++ b/app/LLM/Qwen.php @@ -144,7 +144,7 @@ public function streamResponse() // log $event = json_decode($d, true); -// Log::debug('event', $event); + // Log::debug('event', $event); if (isset($event['choices'][0])) { $finish_reason = $event['choices'][0]['finish_reason']; @@ -155,12 +155,12 @@ public function streamResponse() $this->history->addMessage($ai_message); yield $ai_message; -// Log::debug('stop!'); + // Log::debug('stop!'); break; } elseif ($finish_reason == 'tool_calls') { $this->retry = true; -// Log::debug('finished_reason is tool call, set retry'); + // Log::debug('finished_reason is tool call, set retry'); } $delta = $event['choices'][0]['delta']; @@ -179,7 +179,7 @@ public function streamResponse() yield $tool_req; -// Log::debug('tool req', [$tool_req]); + // Log::debug('tool req', [$tool_req]); $tool_call_message = new AIToolCallMessage(content: ''); $tool_call_message->tool_calls = [ @@ -195,8 +195,8 @@ public function streamResponse() $this->history->addMessage($tool_call_message); $this->history->addMessage($tool_response_message); -// Log::debug('tool call message', [$tool_call_message]); -// Log::debug('tool response', [$tool_response_message]); + // Log::debug('tool call message', [$tool_call_message]); + // Log::debug('tool response', [$tool_response_message]); yield $tool_call_message; yield $tool_response_message; @@ -229,7 +229,7 @@ public function streamResponse() yield $ai_chunk_message; -// Log::debug('chunk', [$ai_chunk_message]); + // Log::debug('chunk', [$ai_chunk_message]); } $this->retry = false; diff --git a/app/Logic/LLMTool.php b/app/Logic/LLMTool.php index bd3f0ea..59cedd8 100644 --- a/app/Logic/LLMTool.php +++ b/app/Logic/LLMTool.php @@ -11,6 +11,7 @@ class LLMTool { protected Tool $tool; + protected User $user; public function setTool(int $tool_id): void @@ -18,7 +19,7 @@ public function setTool(int $tool_id): void $this->tool = Tool::findOrFail($tool_id); } - public function setUser(User $user):void + public function setUser(User $user): void { $this->user = $user; } @@ -46,15 +47,15 @@ public function callTool(string $function_name, $parameters = []): FunctionCall if (empty($this->tool->api_key)) { $r->success = false; - $r->result = "[Error] 没有找到 API KEY,请先在工具设置中设置 API KEY。"; + $r->result = '[Error] 没有找到 API KEY,请先在工具设置中设置 API KEY。'; return $r; } - if (!empty($this->user)) { + if (! empty($this->user)) { $data['user'] = [ 'id' => $this->user->external_id, - 'name' => $this->user->name + 'name' => $this->user->name, ]; } diff --git a/config/app.php b/config/app.php index f467267..c97cdc9 100644 --- a/config/app.php +++ b/config/app.php @@ -65,7 +65,7 @@ | */ - 'timezone' => env('APP_TIMEZONE', 'UTC'), + 'timezone' => env('APP_TIMEZONE', 'PRC'), /* |-------------------------------------------------------------------------- @@ -119,7 +119,7 @@ */ 'maintenance' => [ - 'driver' => env('APP_MAINTENANCE_DRIVER', 'file'), + 'driver' => env('APP_MAINTENANCE_DRIVER', 'cache'), 'store' => env('APP_MAINTENANCE_STORE', 'database'), ], diff --git a/config/filesystems.php b/config/filesystems.php index c5f244d..a4d06d6 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -13,7 +13,7 @@ | */ - 'default' => env('FILESYSTEM_DISK', 'local'), + 'default' => env('FILESYSTEM_DISK', 's3'), /* |-------------------------------------------------------------------------- @@ -29,21 +29,6 @@ */ 'disks' => [ - - 'local' => [ - 'driver' => 'local', - 'root' => storage_path('app'), - 'throw' => false, - ], - - 'public' => [ - 'driver' => 'local', - 'root' => storage_path('app/public'), - 'url' => env('APP_URL').'/storage', - 'visibility' => 'public', - 'throw' => false, - ], - 's3' => [ 'driver' => 's3', 'key' => env('AWS_ACCESS_KEY_ID'), @@ -52,7 +37,7 @@ 'bucket' => env('AWS_BUCKET'), 'url' => env('AWS_URL'), 'endpoint' => env('AWS_ENDPOINT'), - 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), + 'use_path_style_endpoint' => true, 'throw' => false, ], diff --git a/config/mail.php b/config/mail.php index df13d3d..fe5a072 100644 --- a/config/mail.php +++ b/config/mail.php @@ -14,7 +14,7 @@ | */ - 'default' => env('MAIL_MAILER', 'log'), + 'default' => env('MAIL_MAILER', 'smtp'), /* |-------------------------------------------------------------------------- diff --git a/config/queue.php b/config/queue.php index 116bd8d..b54bc33 100644 --- a/config/queue.php +++ b/config/queue.php @@ -13,7 +13,7 @@ | */ - 'default' => env('QUEUE_CONNECTION', 'database'), + 'default' => env('QUEUE_CONNECTION', 'redis'), /* |-------------------------------------------------------------------------- @@ -29,40 +29,10 @@ */ 'connections' => [ - 'sync' => [ 'driver' => 'sync', ], - 'database' => [ - 'driver' => 'database', - 'connection' => env('DB_QUEUE_CONNECTION'), - 'table' => env('DB_QUEUE_TABLE', 'jobs'), - 'queue' => env('DB_QUEUE', 'default'), - 'retry_after' => (int) env('DB_QUEUE_RETRY_AFTER', 90), - 'after_commit' => false, - ], - - 'beanstalkd' => [ - 'driver' => 'beanstalkd', - 'host' => env('BEANSTALKD_QUEUE_HOST', 'localhost'), - 'queue' => env('BEANSTALKD_QUEUE', 'default'), - 'retry_after' => (int) env('BEANSTALKD_QUEUE_RETRY_AFTER', 90), - 'block_for' => 0, - 'after_commit' => false, - ], - - 'sqs' => [ - 'driver' => 'sqs', - 'key' => env('AWS_ACCESS_KEY_ID'), - 'secret' => env('AWS_SECRET_ACCESS_KEY'), - 'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'), - 'queue' => env('SQS_QUEUE', 'default'), - 'suffix' => env('SQS_SUFFIX'), - 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), - 'after_commit' => false, - ], - 'redis' => [ 'driver' => 'redis', 'connection' => env('REDIS_QUEUE_CONNECTION', 'default'), diff --git a/init.php b/init.php new file mode 100644 index 0000000..33a66c3 --- /dev/null +++ b/init.php @@ -0,0 +1,50 @@ +group(function () { +Route::middleware(['auth:api,web', CORSMiddleware::class])->group(function () { Route::get('/user', function (Request $request) { return $request->user(); }); @@ -23,4 +24,4 @@ Route::delete('assistants/{assistant}/tools/{tool}', [AssistantToolController::class, 'destroy']); }); -Route::get('chat_stream/{stream_id}', [ChatHistoryController::class, 'stream'])->name('chat-stream'); +Route::middleware(CORSMiddleware::class)->get('chat_stream/{stream_id}', [ChatHistoryController::class, 'stream'])->name('chat-stream');