symfony/ai-gemini-platform
Symfony AI bridge for Google’s Gemini platform. Integrates Gemini generateContent (incl. streaming) and embeddings APIs, linking to official docs and API reference. Includes licensed media fixtures for tests and points to the main Symfony AI repo for issues/PRs.
Install the Package
composer require symfony/ai-gemini-platform
Ensure your composer.json includes Symfony’s HTTP client and Messenger components if not already present.
Configure the Client
Add to config/services.php:
'gemini' => [
'api_key' => env('GEMINI_API_KEY'),
'endpoint' => env('GEMINI_ENDPOINT', 'https://generativelanguage.googleapis.com/v1'),
'default_model' => env('GEMINI_MODEL', 'gemini-3.1-pro-preview'),
],
Bind the Client in Laravel
In App\Providers\AppServiceProvider:
use Symfony\Component\AI\Gemini\Client\GeminiClient;
use Symfony\Component\AI\Gemini\Client\ModelClient;
public function register()
{
$this->app->singleton(GeminiClient::class, function ($app) {
return new GeminiClient(
$app['config']['services.gemini.api_key'],
$app['config']['services.gemini.endpoint']
);
});
}
First Use Case: Text Generation
use Symfony\Component\AI\Gemini\Client\ModelClient;
public function generateText()
{
$client = app(ModelClient::class);
$response = $client->generateContent(
'gemini-3.1-pro-preview',
'Explain Laravel dependency injection in simple terms.'
);
return $response->getContent();
}
Environment Variables
Add to .env:
GEMINI_API_KEY=your_api_key_here
GEMINI_MODEL=gemini-3.1-pro-preview
$client = app(ModelClient::class);
$response = $client->generateContent(
'gemini-3.1-pro-preview',
'Write a blog post about Laravel AI integrations.'
);
$content = $response->getContent(); // Full response
Useful for real-time UIs (e.g., chatbots):
$response = $client->generateContent(
'gemini-3.1-pro-preview',
'Explain Laravel queues.',
['stream' => true]
);
foreach ($response->getDeltas() as $delta) {
echo $delta->getContent(); // Process chunk-by-chunk
}
use Symfony\Component\AI\Content\MultiPartContent;
$content = new MultiPartContent();
$content->addText('Summarize this document:');
$content->addFile('path/to/document.pdf');
$response = $client->generateContent(
'gemini-3.1-pro-preview',
$content
);
$embeddings = $client->batchEmbedContents(
'models/embedding-001',
['text1', 'text2', 'text3']
);
// Store embeddings in PostgreSQL pgvector or Pinecone
$tools = [
new ServerTool(
'get_weather',
'Fetch weather data for a location',
['parameters' => ['location' => 'string']],
'http://your-api/weather'
)
];
$response = $client->generateContent(
'gemini-3.1-pro-preview',
'What is the weather in Paris?',
['tools' => $tools]
);
Configure in config/services.php:
'gemini' => [
'providers' => [
'default' => 'gemini-3.1-pro-preview',
'flash' => 'gemini-3-flash-preview',
],
],
Use in code:
$client->generateContent('flash', 'Quick response needed.');
Queue Background Jobs Wrap long-running Gemini calls (e.g., batch embeddings) in Laravel queues:
use Illuminate\Support\Facades\Bus;
Bus::dispatch(new GenerateEmbeddingsJob($texts));
Laravel Events for Responses Trigger events after Gemini responses:
event(new GeminiResponseGenerated($response));
API Rate Limiting
Use Laravel’s throttle middleware or Symfony’s RetryMiddleware:
$client->withOptions([
'middleware' => [
new RetryMiddleware(),
new ThrottleMiddleware(10), // 10 requests/minute
],
]);
File Uploads Handle file uploads from Laravel requests:
$file = $request->file('document');
$content = new MultiPartContent();
$content->addFile($file->path());
Caching Responses Cache frequent Gemini responses using Laravel’s cache:
$cacheKey = 'gemini:summary:' . md5($content);
$response = Cache::remember($cacheKey, now()->addHours(1), function () use ($client, $content) {
return $client->generateContent('gemini-3.1-pro-preview', $content);
});
Streaming Chunk Handling
DeltaInterface chunks. Laravel’s synchronous request handling may block.queue or event system to process chunks asynchronously:
$response->getDeltas()->map(function ($delta) {
event(new GeminiChunkReceived($delta));
});
Multipart Content Size Limits
$content->addFile($file->path(), ['mime_type' => 'application/pdf', 'chunk_size' => 5_000_000]);
Tool Use Errors
ToolException:
try {
$response = $client->generateContent(..., ['tools' => $tools]);
} catch (ToolException $e) {
Log::error('Tool failed:', ['error' => $e->getToolErrors()]);
}
Preview Model Instability
gemini-3.1-pro-preview) may change or deprecate.$models = ['gemini-3.1-pro-preview', 'gemini-3-flash-preview'];
foreach ($models as $model) {
try {
return $client->generateContent($model, $prompt);
} catch (ModelNotAvailableException) {
continue;
}
}
Binary Data Handling
$content->addFile(base64_encode(file_get_contents($file)));
Enable Symfony Debug Mode
Add to config/app.php:
'debug' => env('APP_DEBUG', true),
This provides detailed error messages for Gemini API failures.
Log Raw API Responses Wrap the client with a custom middleware to log requests/responses:
$client->withOptions([
'middleware' => [
new LoggingMiddleware(),
],
]);
Validate API Keys
Ensure your GEMINI_API_KEY is correct and has permissions for the models you’re using.
Check Rate Limits Gemini enforces rate limits. Monitor usage via:
$client->getLastResponse()->getHeaders()['x-ratelimit-remaining'];
Provider abstraction to add logic (e.g., cost-based model selection):
class CostAwareProvider implements ProviderInterface
{
public function getModel(string $name, array $options): string
{
if ($options['cost_efficient'] ?? false) {
return 'gemini-3-flash-preview';
}
return 'gemini-3.1-pro-preview';
}
}
How can I help you explore Laravel packages today?