Installation
composer require agence-gw/openai-php-client
Add the service provider in config/app.php:
'providers' => [
// ...
AgenceGw\Openai\OpenaiServiceProvider::class,
],
Configuration Publish the config file:
php artisan vendor:publish --provider="AgenceGw\Openai\OpenaiServiceProvider"
Update .env with your OpenAI API key:
OPENAI_API_KEY=your_api_key_here
First Use Case: Chat Completion
use AgenceGw\Openai\Facades\Openai;
$response = Openai::chat()->create([
'model' => 'gpt-3.5-turbo',
'messages' => [
['role' => 'user', 'content' => 'Hello, how are you?'],
],
]);
echo $response['choices'][0]['message']['content'];
Openai::chat(), Openai::completions(), Openai::embeddings(), etc.config/openai.php (API key, base URL, timeout, etc.).OPENAI_LOG_RESPONSES=true in .env.$response = Openai::chat()->create([
'model' => 'gpt-3.5-turbo',
'messages' => [...],
'stream' => true,
]);
foreach ($response as $chunk) {
echo $chunk['choices'][0]['delta']['content'];
}
$embeddings = Openai::embeddings()->create([
'model' => 'text-embedding-ada-002',
'input' => ['Your text here', 'Another text'],
]);
// Store embeddings in a database (e.g., PostgreSQL with vector support)
try {
$response = Openai::completions()->create([...]);
} catch (\AgenceGw\Openai\Exceptions\OpenaiException $e) {
// Handle rate limits, invalid requests, etc.
logger()->error($e->getMessage());
}
use AgenceGw\Openai\Facades\Openai;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
class GenerateSummaryJob implements ShouldQueue
{
use Queueable;
public function handle()
{
$response = Openai::chat()->create([
'model' => 'gpt-4',
'messages' => [
['role' => 'system', 'content' => 'Summarize the following text.'],
['role' => 'user', 'content' => $this->text],
],
]);
// Save summary to DB
}
}
Override default headers or URLs via config:
// config/openai.php
'headers' => [
'Authorization' => 'Bearer ' . env('OPENAI_API_KEY'),
'Custom-Header' => 'Value',
],
'base_url' => env('OPENAI_CUSTOM_BASE_URL', 'https://api.openai.com/v1'),
Caching Responses: Cache frequent queries (e.g., embeddings) using Laravel's cache:
$cacheKey = 'embeddings_' . md5($input);
$embeddings = cache()->remember($cacheKey, now()->addHours(1), function () use ($input) {
return Openai::embeddings()->create(['input' => $input]);
});
Queue Long-Running Tasks: Offload expensive API calls (e.g., fine-tuning) to queues:
dispatch(new FineTuneJob($dataset));
Testing: Use mocks with Laravel's HTTP testing:
$response = $this->post('/api/generate', ['text' => 'Test']);
$response->assertJson(['summary' => '...']);
Rate Limits
gpt-3.5-turbo).X-RateLimit-* headers in responses.Model Availability
$models = Openai::models()->list();
if (!in_array('gpt-4', $models['data'])) {
throw new \RuntimeException('Model gpt-4 not available');
}
Token Limits
gpt-3.5-turbo) returns truncated responses.max_tokens and validate input length:
$tokenCount = str_word_count($text) / 4; // Approximate
if ($tokenCount > 3000) {
throw new \InvalidArgumentException('Input too long');
}
Streaming Quirks
null or incomplete chunks:
foreach ($response as $chunk) {
if (isset($chunk['choices'][0]['delta']['content'])) {
echo $chunk['choices'][0]['delta']['content'];
}
}
API Key Exposure
.env and restrict file permissions:
chmod 600 .env
Enable Logging
Set OPENAI_LOG_RESPONSES=true in .env to log all requests/responses to storage/logs/openai.log.
Inspect Headers Add custom headers for debugging:
'headers' => [
'X-Debug' => 'true',
],
Validate Payloads Use Laravel's validator to sanitize inputs before sending to OpenAI:
$validated = $request->validate([
'messages.*.content' => 'required|string|max:4096',
]);
Custom Endpoints Extend the client to support OpenAI's beta endpoints (e.g., assistants):
// app/Providers/OpenaiServiceProvider.php
Openai::extend('assistants', function ($app) {
return new \AgenceGw\Openai\Clients\AssistantsClient($app['openai.config']);
});
Middleware Add request/response middleware for logging, retries, or auth:
Openai::middleware(function ($request) {
$request->headers->set('X-Custom-Id', auth()->id());
});
Mocking for Tests Override the HTTP client in tests:
$this->app->singleton(\AgenceGw\Openai\Clients\HttpClient::class, function () {
return new \Mockery\MockInterface();
});
Webhook Integration Use the client to validate OpenAI webhook signatures (e.g., for fine-tuning events):
$signature = $request->header('Openai-Signature');
$payload = $request->getContent();
if (!Openai::validateWebhook($signature, $payload)) {
abort(401);
}
How can I help you explore Laravel packages today?