symfony/ai-vertex-ai-platform
Bridge for using Google Vertex AI Platform with Symfony AI. Supports Gemini inference and text embeddings on Vertex with links to task types and authentication (ADC). Includes test fixtures with licensed media and points to Symfony AI repo for issues/PRs.
Install the Package
Add to your composer.json:
composer require symfony/ai-vertex-ai-platform
Ensure you have symfony/ai (v0.8+) as a dependency.
Configure Authentication
Add Vertex AI credentials to your Symfony config (config/packages/ai.yaml):
ai:
providers:
vertex_ai:
client: 'vertex_ai.client'
project_id: '%env(VERTEX_AI_PROJECT_ID)%'
location: 'us-central1'
# Choose one auth method:
auth:
# ADC (recommended for GCP environments)
adc: true
# OR API key
# api_key: '%env(VERTEX_AI_API_KEY)%'
First Use Case: Text Generation
Inject the GeminiClient and call a model:
use Symfony\AI\Gemini\GeminiClient;
use Symfony\AI\Gemini\Model\ChatCompletion;
class MyService {
public function __construct(private GeminiClient $gemini) {}
public function generateText(): string {
$response = $this->gemini->chatCompletion(
new ChatCompletion('gemini-1.5-flash-latest'),
['messages' => [['role' => 'user', 'content' => 'Hello!']]]
);
return $response->getChoices()[0]->getMessage()->getContent();
}
}
Verify with a Test Use Symfony’s test fixtures or mock the client for local testing:
use Symfony\AI\Test\MockGeminiClient;
$mockClient = new MockGeminiClient();
$mockClient->expects('chatCompletion')
->andReturn(new ChatCompletionResponse([new ChatChoice([
new ChatMessage('assistant', 'Hi there!')
])]));
Dynamically route requests based on context (e.g., cost, latency, or model capabilities):
use Symfony\AI\Provider\ProviderInterface;
class HybridAIService {
public function __construct(
private ProviderInterface $vertexProvider,
private ProviderInterface $openAIProvider
) {}
public function generate(string $prompt, bool $useFlashModel = false): string {
$provider = $useFlashModel ? $this->vertexProvider : $this->openAIProvider;
$response = $provider->chatCompletion(
new ChatCompletion($useFlashModel ? 'gemini-1.5-flash-latest' : 'gpt-4'),
['messages' => [['role' => 'user', 'content' => $prompt]]]
);
return $response->getChoices()[0]->getMessage()->getContent();
}
}
Handle real-time AI interactions (e.g., chatbots) with DeltaInterface:
use Symfony\AI\Gemini\Model\ChatCompletion;
use Symfony\AI\Streaming\StreamingResponse;
public function streamChatResponse(string $prompt): StreamingResponse {
$response = $this->gemini->chatCompletion(
new ChatCompletion('gemini-1.5-flash-latest'),
['messages' => [['role' => 'user', 'content' => $prompt]]],
['stream' => true]
);
return new StreamingResponse(function () use ($response) {
foreach ($response->getChoices()[0]->getMessage()->getContentDeltas() as $delta) {
yield $delta->getContent();
}
});
}
Generate embeddings for vector databases (e.g., FAISS, Weaviate):
use Symfony\AI\Gemini\Model\Embedding;
public function generateEmbedding(string $text): array {
$response = $this->gemini->embedding(
new Embedding('text-embedding-004'),
['input' => [$text]]
);
return $response->getEmbeddings()[0]->getValues();
}
Handle images, audio, or documents alongside text:
use Symfony\AI\Gemini\Model\MultipartChatCompletion;
public function analyzeDocument(string $filePath, string $prompt): string {
$response = $this->gemini->multipartChatCompletion(
new MultipartChatCompletion('gemini-1.5-flash-latest'),
[
'contents' => [
['mime_type' => 'application/pdf', 'data' => file_get_contents($filePath)],
['role' => 'user', 'parts' => [['text' => $prompt]]]
]
]
);
return $response->getChoices()[0]->getMessage()->getContent();
}
cloud-platform scope.ai:
providers:
vertex_ai:
auth:
api_key: '%env(VERTEX_AI_API_KEY)%'
Wrap calls in try-catch blocks to handle Vertex AI-specific errors:
try {
$response = $this->gemini->chatCompletion(...);
} catch (\Symfony\AI\Exception\VertexAIException $e) {
// Log or retry with a fallback model
$this->logger->error('Vertex AI error: ' . $e->getMessage());
throw new \RuntimeException('AI service unavailable', 0, $e);
}
Use environment variables for sensitive data:
# .env
VERTEX_AI_PROJECT_ID=your-project-id
VERTEX_AI_LOCATION=us-central1
VERTEX_AI_API_KEY=${VERTEX_AI_API_KEY:-} # Optional
Bind the client to a specific model or use interfaces for flexibility:
// config/services.yaml
services:
Symfony\AI\Gemini\GeminiClient:
arguments:
$model: 'gemini-1.5-flash-latest'
$provider: '@ai.provider.vertex_ai'
Use Symfony’s test utilities to mock responses:
use Symfony\AI\Test\MockGeminiClient;
$mockClient = new MockGeminiClient();
$mockClient->expects('chatCompletion')
->withArgs(function ($model, $args) {
return $model->getModelName() === 'gemini-1.5-flash-latest';
})
->andReturn(new ChatCompletionResponse([new ChatChoice([
new ChatMessage('assistant', 'Mocked response!')
])]));
GOOGLE_APPLICATION_CREDENTIALS or Compute Engine metadata).
Fix: Explicitly set ADC in config:
ai:
providers:
vertex_ai:
auth:
adc: true
Vertex AI User or Vertex AI Service Agent roles.
Fix: Regenerate the key in GCP IAM.gemini-1.0). Check Vertex AI docs for updates.
Fix: Use the ModelCatalog to list available models:
$catalog = $this->gemini->getModelCatalog();
$models = $catalog->getModels();
$chunkedData = array_chunk(file_get_contents($filePath), 5_000_000);
text-embedding-004).
Fix: Truncate long texts or use smaller models:
$text = substr($longText, 0, 8000); // Adjust based on model limits
$response = $
How can I help you explore Laravel packages today?