├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── composer.json ├── config └── gpt.php ├── logo.webp └── src ├── Facades └── GPT.php ├── GPTService.php ├── GPTServiceProvider.php ├── Serializable └── GPTSerializable.php └── Support ├── GPTException.php └── GPTResponse.php /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to `laravel-gpt` will be documented in this file. 4 | 5 | ## [Unreleased](https://github.com/capevace/laravel-gpt/compare/v1.0.1...HEAD) 6 | 7 | ## v1.0.0 - 2022-12-13 8 | 9 | Release of the initial version 10 | 11 | ## [v1.0.1](https://github.com/capevace/laravel-gpt/compare/1.0.0...v1.0.1) - 2022-12-13 12 | 13 | ### Removed 14 | 15 | - Removed internal Serializables 16 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Lukas Mateffy 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 |
2 | 3 | 4 | 5 |

laravel-gpt

6 |

7 | This package provides a type-safe interface for making requests to the GPT-3 API. 8 |

9 |

10 | 11 | Latest Version on Packagist 12 | 13 | 14 | GitHub Tests Action Status 15 | 16 | 17 | Total Downloads 18 | 19 |

20 |
21 | 22 | ```php 23 | use Capevace\GPT\Facades\GPT; 24 | 25 | $response = GPT::generate( 26 | 'Name a thing that is blue.', 27 | model: 'text-davinci-003', 28 | maxTokens: 400, 29 | frequencyPenalty: 1.0, 30 | ); 31 | 32 | echo $response->first(); // "The sky" 33 | ``` 34 | 35 |
36 | 37 | ## Installation 38 | 39 | You can install the package via composer: 40 | 41 | ```bash 42 | composer require capevace/laravel-gpt 43 | ``` 44 | 45 |
46 | 47 | ## Configuration 48 | 49 | You will need an API key for the OpenAI GPT-3 API. Once you have obtained an API key, you can configure it in your .env file by adding the following line: 50 | 51 | ```bash 52 | OPENAI_API_KEY=your-api-key-here 53 | ``` 54 | 55 | You could also publish the config file directly, **but this really probably isn't necessary**: 56 | 57 | ```bash 58 | php artisan vendor:publish --tag="laravel-gpt-config" 59 | ``` 60 | 61 |
62 | 63 | ## Usage 64 | 65 | The `Capevace\GPT\GPTService` class provides methods for making requests to the GPT-3 API. You can inject it into controllers or use the Facade to access the container. 66 | 67 | ```php 68 | # Access via injection 69 | 70 | use Capevace\GPT\GPTService; 71 | 72 | class MyController extends Controller { 73 | protected GPTService $gpt; 74 | 75 | public function __construct(GPTService $gpt) { 76 | $this->gpt = $gpt; 77 | } 78 | 79 | public function index() { 80 | $this->gpt->generate( 81 | // .. 82 | ); 83 | } 84 | 85 | } 86 | 87 | # Access via Facade 88 | 89 | use Capevace\GPT\Facades\GPT; 90 | 91 | GPT::generate(/* .. */); 92 | ``` 93 | 94 |
95 | 96 | ### GPT::generate(_\_, _[...options]_) 97 | 98 | The `generate` method returns a `GPTResponse` object that contains the response from the GPT-3 API. If no text is returned (empty string), the method will throw an error. 99 | 100 | `generate` takes the following arguments: 101 | 102 | - `prompt` (required): the prompt to send to the GPT-3 API 103 | - `model`: the GPT-3 model to use (defaults to text-davinci-003) 104 | - `temperature`: a value between 0 and 1 that determines how "creative" the response will be (defaults to 0.83) 105 | - `maxTokens`: the maximum number of tokens (i.e., words) to return in the response (defaults to 1200) 106 | - `stop`: a string that, when encountered in the response, will cause the response to end (defaults to null) 107 | - `frequencyPenalty`: a value between 0 and 1 that determines how much the model will penalize frequent words (defaults to 0.11) 108 | - `presencePenalty`: a value between 0 and 1 that determines how much the model will penalize words that don't appear in the prompt (defaults to 0.03) 109 | 110 | #### Example 111 | 112 | ```php 113 | use Capevace\GPT\Facades\GPT; 114 | 115 | $response = GPT::generate( 116 | 'Generate a list of things that are blue.', 117 | model: 'text-davinci-003', 118 | maxTokens: 400, 119 | frequencyPenalty: 1.0, 120 | ); 121 | ``` 122 | 123 |
124 | 125 | ### Handling responses 126 | 127 | The `generate` method returns a `GPTResponse` object that contains the response from the GPT-3 API. 128 | 129 | It has two methods: 130 | 131 | - `$response->first()` (_string_): returns the first text suggested by GPT-3 132 | - `$response->all()` (_array_): returns a list of all the text choices suggested by GPT-3 133 | 134 | #### Example 135 | 136 | ```php 137 | use Capevace\GPT\Facades\GPT; 138 | 139 | $response = GPT::generate( 140 | 'Name a thing that is blue.', 141 | model: 'text-davinci-003', 142 | maxTokens: 400, 143 | frequencyPenalty: 1.0, 144 | ); 145 | 146 | $firstChoice = $response->first(); // "the sky" 147 | 148 | $allChoices = $response->all(); // ["the sky", "the ocean" ...] 149 | ``` 150 | 151 |
152 | 153 | ### Error handling 154 | 155 | If an error occurs while making a request to the GPT-3 API, the `generate()` method will throw a `Capevace\GPT\Support\GPTException` exception. 156 | 157 | `laravel-gpt` will also throw an error, if a response does not contain any text (empty string). 158 | 159 | #### Example 160 | 161 | ```php 162 | use Capevace\GPT\Facades\GPT; 163 | use Capevace\GPT\Support\GPTException; 164 | use Exception; 165 | 166 | try { 167 | $response = GPT::generate('Do nothing.'); 168 | } catch (GPTException $e) { 169 | // Exception will be thrown, as the response text is "" 170 | } catch (Exception $e) { 171 | // Catch connectivity errors etc. 172 | } 173 | ``` 174 | 175 |
176 | 177 | --- 178 | 179 | ## Changelog 180 | 181 | Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. 182 | 183 | ## License 184 | 185 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 186 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "capevace/laravel-gpt", 3 | "description": "A Laravel package for interacting with OpenAI's GPT-3.", 4 | "keywords": [ 5 | "capevace", 6 | "laravel", 7 | "ai", 8 | "gpt", 9 | "openai", 10 | "gpt-3", 11 | "text-generation", 12 | "llm", 13 | "language-model" 14 | ], 15 | "homepage": "https://github.com/capevace/laravel-gpt", 16 | "license": "MIT", 17 | "authors": [ 18 | { 19 | "name": "Lukas Mateffy", 20 | "email": "github@mateffy.me", 21 | "role": "Developer" 22 | } 23 | ], 24 | "require": { 25 | "php": "^8.1", 26 | "illuminate/contracts": "^9.0", 27 | "orhanerday/open-ai": "^3.2", 28 | "spatie/laravel-package-tools": "^1.13.0" 29 | }, 30 | "require-dev": { 31 | "laravel/pint": "^1.0", 32 | "nunomaduro/collision": "^6.0", 33 | "nunomaduro/larastan": "^2.0.1", 34 | "orchestra/testbench": "^7.0", 35 | "pestphp/pest": "^1.21", 36 | "pestphp/pest-plugin-laravel": "^1.1", 37 | "phpstan/extension-installer": "^1.1", 38 | "phpstan/phpstan-deprecation-rules": "^1.0", 39 | "phpstan/phpstan-phpunit": "^1.0", 40 | "phpunit/phpunit": "^9.5", 41 | "spatie/laravel-ray": "^1.26" 42 | }, 43 | "autoload": { 44 | "psr-4": { 45 | "Capevace\\GPT\\": "src" 46 | } 47 | }, 48 | "autoload-dev": { 49 | "psr-4": { 50 | "Capevace\\GPT\\Tests\\": "tests" 51 | } 52 | }, 53 | "scripts": { 54 | "post-autoload-dump": "@php ./vendor/bin/testbench package:discover --ansi", 55 | "analyse": "vendor/bin/phpstan analyse", 56 | "test": "vendor/bin/pest", 57 | "test-coverage": "vendor/bin/pest --coverage", 58 | "format": "vendor/bin/pint" 59 | }, 60 | "config": { 61 | "sort-packages": true, 62 | "allow-plugins": { 63 | "pestphp/pest-plugin": true, 64 | "phpstan/extension-installer": true 65 | } 66 | }, 67 | "extra": { 68 | "laravel": { 69 | "providers": [ 70 | "Capevace\\GPT\\GPTServiceProvider" 71 | ], 72 | "aliases": { 73 | "GPT": "Capevace\\GPT\\Facades\\GPT" 74 | } 75 | } 76 | }, 77 | "minimum-stability": "dev", 78 | "prefer-stable": true 79 | } 80 | -------------------------------------------------------------------------------- /config/gpt.php: -------------------------------------------------------------------------------- 1 | env('OPENAI_API_KEY'), 6 | ]; 7 | -------------------------------------------------------------------------------- /logo.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Capevace/laravel-gpt/bbaed565b86f54d41e8a8294777b595d0265b7f5/logo.webp -------------------------------------------------------------------------------- /src/Facades/GPT.php: -------------------------------------------------------------------------------- 1 | openAi = new OpenAi($apiKey); 26 | } 27 | 28 | $this->shouldLog = env('OPENAI_LOG_RESPONSES', false); 29 | } 30 | 31 | protected function getOpenAI(): OpenAi 32 | { 33 | if ($this->openAi === null) { 34 | throw new GPTException('OpenAI API key not configured.', 'no-api-key'); 35 | } 36 | 37 | return $this->openAi; 38 | } 39 | 40 | /** 41 | * Sends a request to the GPT3 API. 42 | * 43 | * @param string $prompt The prompt to send to the API. 44 | * @param string $model The model to use. 45 | * @param float $temperature 46 | * @param int $maxTokens 47 | * @param ?string $stop 48 | * @param float $frequencyPenalty 49 | * @param float $presencePenalty 50 | * @return GPTResponse 51 | * 52 | * @throws GPTException 53 | */ 54 | public function generate( 55 | string $prompt, 56 | string $model = 'text-davinci-003', 57 | float $temperature = 0.83, 58 | int $maxTokens = 1200, 59 | ?string $stop = null, 60 | float $frequencyPenalty = 0.11, 61 | float $presencePenalty = 0.03, 62 | ): GPTResponse { 63 | $json = $this 64 | ->getOpenAI() 65 | ->completion([ 66 | 'model' => $model, 67 | 'prompt' => $prompt, 68 | 'temperature' => $temperature, 69 | 'max_tokens' => $maxTokens, 70 | 'stop' => $stop, 71 | 'frequency_penalty' => $frequencyPenalty, 72 | 'presence_penalty' => $presencePenalty, 73 | ]); 74 | 75 | $response = GPTResponse::fromJSON($json); 76 | 77 | if ($this->shouldLog) { 78 | Storage::disk('gpt') 79 | ->put( 80 | 'offer-'.Str::uuid().'.json', 81 | json_encode( 82 | [ 83 | 'prompt' => $prompt, 84 | 'result' => $response->first(), 85 | ] 86 | ) 87 | ); 88 | } 89 | 90 | return $response; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/GPTServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->bind(GPTService::class, function ($app) { 28 | return new GPTService(); 29 | }); 30 | } 31 | 32 | public function configurePackage(Package $package): void 33 | { 34 | /* 35 | * This class is a Package Service Provider 36 | * 37 | * More info: https://github.com/spatie/laravel-package-tools 38 | */ 39 | $package 40 | ->name('gpt') 41 | ->hasConfigFile(); 42 | // ->hasCommand(LaravelGptCommand::class); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Serializable/GPTSerializable.php: -------------------------------------------------------------------------------- 1 | first(fn ($choice) => ! property_exists($choice, 'text') || ! filled($choice->text))) { 31 | throw new GPTException('OpenAI returned an empty choice', 'empty-choice'); 32 | } 33 | 34 | if (count($choices) === 0) { 35 | throw new GPTException('OpenAI returned no choices', 'no-choices'); 36 | } 37 | 38 | if (! property_exists($choices[0], 'text') || ! filled($choices[0]->text)) { 39 | throw new GPTException('OpenAI returned a choice without text', 'no-text'); 40 | } 41 | 42 | $this->first = $choices[0]->text; 43 | } 44 | 45 | /** 46 | * Returns the `$first` property of the `GPTResponse` instance. 47 | * 48 | * @return string The first choice in the response. 49 | */ 50 | public function first(): string 51 | { 52 | return $this->first; 53 | } 54 | 55 | /** 56 | * Get all choices by GPT-3. 57 | * 58 | * @return string[] All choices in the response. 59 | */ 60 | public function all(): array 61 | { 62 | return $this->choices; 63 | } 64 | 65 | /** 66 | * Takes a JSON string representing a GPT-3 response and returns a new `GPTResponse` instance. 67 | * If the JSON cannot be decoded, it throws a `GPTException` with the message "Unknown GPT-3 error" and the error type "unknown". 68 | * If the decoded JSON contains an error property, it throws a `GPTException` with the error message and error type specified in the JSON. 69 | * 70 | * @param string $json A JSON string representing a GPT-3 response. 71 | * @return GPTResponse A new `GPTResponse` instance. 72 | * 73 | * @throws GPTException if the JSON cannot be decoded or if it contains an error property. 74 | */ 75 | public static function fromJSON(string $json): GPTResponse 76 | { 77 | $data = json_decode($json); 78 | 79 | if ($data === null) { 80 | throw new GPTException('Unknown GPT-3 error', 'unknown'); 81 | } 82 | 83 | if (property_exists($data, 'error')) { 84 | throw new GPTException($data->error->message, $data->error->type); 85 | } 86 | 87 | return new GPTResponse($data->choices); 88 | } 89 | } 90 | --------------------------------------------------------------------------------