├── LICENSE.md ├── README.md ├── composer.json └── src ├── ModelVersionIdentifier.php ├── Replicate.php ├── Requests ├── CancelPredictionRequest.php ├── CancelTrainingRequest.php ├── CreateDreamboothTrainingRequest.php ├── CreateModelPredictionRequest.php ├── CreateModelRequest.php ├── CreatePredictionRequest.php ├── CreateTrainingRequest.php ├── CreateUploadRequest.php ├── GetAllModelVersionsRequest.php ├── GetAllPredictionsRequest.php ├── GetAllTrainingsRequest.php ├── GetDreamboothRequest.php ├── GetModelRequest.php ├── GetModelVersionRequest.php ├── GetPredictionRequest.php ├── GetTrainingRequest.php ├── UpdateUploadRequest.php └── UploadTrainingImagesRequest.php └── Resources ├── ModelResource.php ├── PredictionResource.php ├── Resource.php ├── TrainingResource.php └── UploadResource.php /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) SabatinoMasala 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PHP client for the Replicate API 2 | 3 | This is a PHP client for Replicate. It lets you run models from your PHP code and do various other things on Replicate. 4 | 5 | ## Credits 6 | 7 | This package is based on the work of https://github.com/sawirricardo/replicate-php 8 | 9 | ## Video 10 | 11 | If you're a more visual learner, you can check out this video this package is showcased: 12 | 13 | [![Watch the video](https://i3.ytimg.com/vi/gSGYvXG5kcQ/maxresdefault.jpg)](https://youtu.be/gSGYvXG5kcQ) 14 | 15 | ## Installation 16 | 17 | You can install the package via composer: 18 | 19 | ```bash 20 | composer require sabatinomasala/replicate-php 21 | ``` 22 | 23 | ## Getting an API token 24 | 25 | You can get an API token from [https://replicate.com/account/api-tokens]([url](https://replicate.com/account/api-tokens)) 26 | 27 | ## Creating a prediction 28 | 29 | You can create a prediction as follows: 30 | 31 | ```php 32 | // Create a prediction 33 | $prediction = $client->predictions()->create('stability-ai/sdxl:7762fd07cf82c948538e41f63f77d685e02b063e37e496e96eefd46c929f9bdc', [ 34 | 'prompt' => 'a cat wearing a cowboy hat', 35 | ]); 36 | 37 | $id = $prediction->json('id'); 38 | 39 | // Fetch prediction 40 | $prediction = $client->predictions()->get($id); 41 | dd($prediction->json()) 42 | 43 | ``` 44 | 45 | ## Running a model 46 | 47 | You can run a model and wait on the output as follows: 48 | 49 | ```php 50 | $token = env('REPLICATE_TOKEN'); 51 | $client = new SabatinoMasala\Replicate\Replicate($token); 52 | $output = $client->run('stability-ai/sdxl:7762fd07cf82c948538e41f63f77d685e02b063e37e496e96eefd46c929f9bdc', [ 53 | 'prompt' => 'a cat wearing a cowboy hat', 54 | ], function($prediction) { 55 | // You can log the current state of the prediction 56 | \Log::info('Progress', $prediction->json()); 57 | }); 58 | 59 | dd($output[0]); 60 | ``` 61 | 62 | ### Chaining multiple models 63 | 64 | Because 'run' returns the output of the model, you can chain multiple models together like this: 65 | 66 | ```php 67 | $output = $client->run('stability-ai/sdxl:7762fd07cf82c948538e41f63f77d685e02b063e37e496e96eefd46c929f9bdc', [ 68 | 'prompt' => 'a cat wearing a cowboy hat', 69 | ]); 70 | 71 | $caption = $client->run('salesforce/blip:2e1dddc8621f72155f24cf2e0adbde548458d3cab9f00c0139eea840d0ac4746', [ 72 | 'task' => 'image_captioning', 73 | 'image' => $output[0], 74 | ]); 75 | 76 | dd($caption); // Caption: a drawing of a cat wearing a cowboy hat 77 | ``` 78 | 79 | ## Usage with official models 80 | 81 | Offical models, like Llama, have a different API endpoint. This client automatically switches endpoints, based on the input you give: 82 | 83 | ```php 84 | // This will do an API call to https://api.replicate.com/v1/models/meta/meta-llama-3-70b-instruct/predictions instead of https://api.replicate.com/v1/predictions 85 | $output = $replicate->run('meta/meta-llama-3-70b-instruct', [ 86 | 'prompt' => 'I want to travel to Japan, give me an itinerary', 87 | 'max_tokens' => 1000, 88 | ], function($prediction) { 89 | \Log::info($prediction->json('output')); 90 | }); 91 | ``` 92 | 93 | ## Credits 94 | - Original creator of replicate-php: [sawirricardo](https://github.com/sawirricardo) 95 | - [sabatinomasala](https://github.com/sabatinomasala) 96 | 97 | ## License 98 | 99 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 100 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sabatinomasala/replicate-php", 3 | "description": "PHP client for the Replicate API", 4 | "keywords": [ 5 | "SabatinoMasala", 6 | "replicate-php", 7 | "replicate", 8 | "machine", 9 | "learning", 10 | "AI", 11 | "artificial", 12 | "intelligence" 13 | ], 14 | "homepage": "https://github.com/SabatinoMasala/replicate-php", 15 | "license": "MIT", 16 | "authors": [ 17 | { 18 | "name": "SabatinoMasala", 19 | "email": "masalasabatino@gmail.com", 20 | "role": "Developer" 21 | } 22 | ], 23 | "require": { 24 | "php": "^8.1", 25 | "saloonphp/saloon": "^2.5" 26 | }, 27 | "require-dev": { 28 | "laravel/pint": "^1.2", 29 | "spatie/ray": "^1.28" 30 | }, 31 | "autoload": { 32 | "psr-4": { 33 | "SabatinoMasala\\Replicate\\": "src" 34 | } 35 | }, 36 | "scripts": { 37 | "format": "vendor/bin/pint" 38 | }, 39 | "config": { 40 | "sort-packages": true, 41 | "allow-plugins": { 42 | "pestphp/pest-plugin": true, 43 | "phpstan/extension-installer": true 44 | } 45 | }, 46 | "minimum-stability": "dev", 47 | "prefer-stable": true 48 | } 49 | -------------------------------------------------------------------------------- /src/ModelVersionIdentifier.php: -------------------------------------------------------------------------------- 1 | owner = $owner; 12 | $this->name = $name; 13 | $this->version = $version; 14 | } 15 | 16 | public static function parse($ref) { 17 | $pattern = '/^(?P[^\/]+)\/(?P[^\/:]+)(:(?P.+))?$/'; 18 | if (!preg_match($pattern, $ref, $matches)) { 19 | throw new Exception('Invalid reference to model version. Expected format: owner/name or owner/name:version. ' . $ref); 20 | } 21 | 22 | $owner = $matches['owner']; 23 | $name = $matches['name']; 24 | $version = $matches['version'] ?? null; 25 | 26 | return new self($owner, $name, $version); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Replicate.php: -------------------------------------------------------------------------------- 1 | withTokenAuth($this->apiKey, 'Token'); 15 | } 16 | 17 | public function predictions() 18 | { 19 | return new PredictionResource($this); 20 | } 21 | 22 | public function run($ref, $options, $progress = null) 23 | { 24 | $wait = $options['wait'] ?? null; 25 | $signal = $options['signal'] ?? null; 26 | $data = $options; 27 | unset($data['wait'], $data['signal']); 28 | 29 | $prediction = $this->predictions()->create($ref, $data); 30 | if ($prediction->clientError()) { 31 | throw new \Exception('Failed to create prediction: ' . json_encode($prediction->json())); 32 | } 33 | 34 | // Call progress callback with the initial prediction object 35 | if ($progress) { 36 | $progress($prediction); 37 | } 38 | 39 | $prediction = $this->wait($prediction, $wait ?? [], function($updatedPrediction) use ($progress, $signal) { 40 | // Call progress callback with the updated prediction object 41 | if ($progress) { 42 | $progress($updatedPrediction); 43 | } 44 | 45 | // We handle the cancel later in the function. 46 | if ($signal && $signal->aborted) { 47 | return true; // stop polling 48 | } 49 | 50 | return false; // continue polling 51 | }); 52 | 53 | if ($signal && $signal->aborted) { 54 | $prediction = $this->predictions()->cancel($prediction->json('id')); 55 | } 56 | 57 | // Call progress callback with the completed prediction object 58 | if ($progress) { 59 | $progress($prediction); 60 | } 61 | 62 | if ($prediction->json('status') === 'failed') { 63 | throw new \Exception('Prediction failed: ' . $prediction->json('error')); 64 | } 65 | 66 | return $prediction->json('output'); 67 | } 68 | 69 | public function models(string $owner, string $name) 70 | { 71 | return new ModelResource($this, $owner, $name); 72 | } 73 | 74 | public function trainings() 75 | { 76 | return new TrainingResource($this); 77 | } 78 | 79 | public function resolveBaseUrl(): string 80 | { 81 | return 'https://api.replicate.com/v1/'; 82 | } 83 | 84 | protected function defaultHeaders(): array 85 | { 86 | return [ 87 | 'Accept' => 'application/json', 88 | 'Content-Type' => 'application/json', 89 | ]; 90 | } 91 | 92 | private function wait($prediction, $options, $stop = null) { 93 | $id = $prediction->json('id') ?? null; 94 | if (!$id) { 95 | throw new \Exception('Invalid prediction'); 96 | } 97 | 98 | if (in_array($prediction->json('status'), ['succeeded', 'failed', 'canceled'])) { 99 | return $prediction; 100 | } 101 | 102 | $interval = $options['interval'] ?? 500; 103 | 104 | $sleep = function ($ms) { 105 | usleep($ms * 1000); 106 | }; 107 | 108 | $updatedPrediction = $this->predictions()->get($id); 109 | 110 | while (!in_array($updatedPrediction->json('status'), ['succeeded', 'failed', 'canceled'])) { 111 | if ($stop && call_user_func($stop, $updatedPrediction) === true) { 112 | break; 113 | } 114 | 115 | $sleep($interval); 116 | $updatedPrediction = $this->predictions()->get($id); 117 | } 118 | 119 | if ($updatedPrediction->json('status') === 'failed') { 120 | throw new \Exception('Prediction failed: ' . $updatedPrediction->json('error')); 121 | } 122 | 123 | return $updatedPrediction; 124 | } 125 | 126 | } 127 | -------------------------------------------------------------------------------- /src/Requests/CancelPredictionRequest.php: -------------------------------------------------------------------------------- 1 | id}/cancel"; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Requests/CancelTrainingRequest.php: -------------------------------------------------------------------------------- 1 | id}/cancel"; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Requests/CreateDreamboothTrainingRequest.php: -------------------------------------------------------------------------------- 1 | model . '/predictions'; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Requests/CreateModelRequest.php: -------------------------------------------------------------------------------- 1 | $this->owner, 26 | 'name' => $this->name, 27 | ]; 28 | } 29 | 30 | public function resolveEndpoint(): string 31 | { 32 | return '/models'; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Requests/CreatePredictionRequest.php: -------------------------------------------------------------------------------- 1 | owner}/{$this->name}/versions/{$this->version}/trainings"; 27 | } 28 | 29 | protected function defaultBody(): array 30 | { 31 | return [ 32 | 'destination' => $this->destination, 33 | ]; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Requests/CreateUploadRequest.php: -------------------------------------------------------------------------------- 1 | name}"; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Requests/GetAllModelVersionsRequest.php: -------------------------------------------------------------------------------- 1 | owner}/{$this->name}/versions"; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Requests/GetAllPredictionsRequest.php: -------------------------------------------------------------------------------- 1 | id}"; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Requests/GetModelRequest.php: -------------------------------------------------------------------------------- 1 | owner}/{$this->name}"; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Requests/GetModelVersionRequest.php: -------------------------------------------------------------------------------- 1 | owner}/{$this->name}/versions/{$this->version}"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Requests/GetPredictionRequest.php: -------------------------------------------------------------------------------- 1 | id}"; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Requests/GetTrainingRequest.php: -------------------------------------------------------------------------------- 1 | id}"; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Requests/UpdateUploadRequest.php: -------------------------------------------------------------------------------- 1 | url; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Requests/UploadTrainingImagesRequest.php: -------------------------------------------------------------------------------- 1 | uploadUrl; 24 | } 25 | 26 | protected function defaultHeaders(): array 27 | { 28 | return [ 29 | 'Content-Type' => 'application/zip', 30 | ]; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Resources/ModelResource.php: -------------------------------------------------------------------------------- 1 | owner = $owner; 22 | $this->name = $name; 23 | } 24 | 25 | public function get() 26 | { 27 | return $this->connector->send(new GetModelRequest($this->owner, $this->name)); 28 | } 29 | 30 | public function allVersions() 31 | { 32 | return $this->connector->send(new GetAllModelVersionsRequest($this->owner, $this->name)); 33 | } 34 | 35 | public function getVersion(string $version) 36 | { 37 | return $this->connector->send(new GetModelVersionRequest($this->owner, $this->name, $version)); 38 | } 39 | 40 | public function create($visibility = 'private', $hardware = 'cpu', $description = null) 41 | { 42 | $req = new CreateModelRequest($this->owner, $this->name); 43 | $req->body()->add('visibility', $visibility); 44 | $req->body()->add('hardware', $hardware); 45 | if (!empty($description)) { 46 | $req->body()->add('description', 'An example model'); 47 | } 48 | return $this->connector->send($req); 49 | } 50 | 51 | public function createTraining(string $version, array $input, string $destination, string $webhook = null) 52 | { 53 | $req = new CreateTrainingRequest($this->owner, $this->name, $version, $destination); 54 | $req->body()->add('input', $input); 55 | if (!empty($webhook)) { 56 | $req->body()->add('webhook', $webhook); 57 | } 58 | 59 | return $this->connector->send($req); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Resources/PredictionResource.php: -------------------------------------------------------------------------------- 1 | version)) { 19 | $req = new CreatePredictionRequest; 20 | $req->body()->add('version', $identifier->version); 21 | } elseif (isset($identifier->owner) && isset($identifier->name)) { 22 | $req = new CreateModelPredictionRequest("{$identifier->owner}/{$identifier->name}"); 23 | } else { 24 | throw new \Exception('Invalid model version identifier'); 25 | } 26 | if (isset($data['webhook'])) { 27 | $req->body()->add('webhook', $data['webhook']); 28 | if (isset($data['webhook_events_filter'])) { 29 | $req->body()->add('webhook_events_filter', $data['webhook_events_filter']); 30 | } 31 | } 32 | $req->body()->add('input', $input); 33 | 34 | return $this->connector->send($req); 35 | } 36 | 37 | public function get(string $id) 38 | { 39 | return $this->connector->send(new GetPredictionRequest($id)); 40 | } 41 | 42 | public function all() 43 | { 44 | return $this->connector->send(new GetAllPredictionsRequest); 45 | } 46 | 47 | public function cancel(string $id) 48 | { 49 | return $this->connector->send(new CancelPredictionRequest($id)); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Resources/Resource.php: -------------------------------------------------------------------------------- 1 | connector->send(new GetTrainingRequest($id)); 16 | } 17 | 18 | public function all() 19 | { 20 | return $this->connector->send(new GetAllTrainingsRequest); 21 | } 22 | 23 | public function cancel(string $id) 24 | { 25 | return $this->connector->send(new CancelTrainingRequest($id)); 26 | } 27 | 28 | public function createDreambooth(string $model, string $trainerVersion, string $webhookCompleted, array $input) 29 | { 30 | $req = new CreateDreamboothTrainingRequest(); 31 | $req->body()->add('model', $model); 32 | $req->body()->add('trainer_version', $trainerVersion); 33 | $req->body()->add('webhook_completed', $webhookCompleted); 34 | $req->body()->add('input', $input); 35 | 36 | return $this->connector->send($req); 37 | } 38 | 39 | public function getDreambooth(string $id) 40 | { 41 | return $this->connector->send(new GetDreamboothRequest($id)); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Resources/UploadResource.php: -------------------------------------------------------------------------------- 1 | connector->send(new CreateUploadRequest(basename($zipPath))); 13 | 14 | $req = new UpdateUploadRequest($res->json('upload_url')); 15 | $req->body()->add(basename($zipPath), fopen($zipPath, 'rb')); 16 | 17 | return $this->connector->send($req)->json('serving_url'); 18 | } 19 | } 20 | --------------------------------------------------------------------------------