Skip to content

[Platform] Add support for Google vertex AI #297

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Symfony AI is a set of components that integrate AI capabilities into PHP applic
Symfony AI consists of several lower and higher level **components** and the respective integration **bundles**:

* **Components**
* **[Platform](src/platform/README.md)**: A unified interface to various AI platforms like OpenAI, Anthropic, Azure, Gemini, and more.
* **[Platform](src/platform/README.md)**: A unified interface to various AI platforms like OpenAI, Anthropic, Azure, Gemini, VertexAI, and more.
* **[Agent](src/agent/README.md)**: Framework for building AI agents that can interact with users and perform tasks.
* **[Store](src/store/README.md)**: Data storage abstraction with indexing and retrieval for AI applications.
* **[MCP SDK](src/mcp-sdk/README.md)**: SDK for [Model Context Protocol](https://modelcontextprotocol.io) enabling communication between AI agents and tools.
Expand Down
4 changes: 4 additions & 0 deletions examples/.env
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ RUN_EXPENSIVE_EXAMPLES=false
# For using Gemini
GEMINI_API_KEY=

# Vertex AI
GOOGLE_CLOUD_LOCATION=global
GOOGLE_CLOUD_PROJECT=GOOGLE_CLOUD_PROJECT

# For using Albert API (French Sovereign AI)
ALBERT_API_KEY=
ALBERT_API_URL=
Expand Down
33 changes: 33 additions & 0 deletions examples/vertexai/audio-input.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\VertexAi\Gemini\Model;
use Symfony\AI\Platform\Bridge\VertexAi\PlatformFactory;
use Symfony\AI\Platform\Message\Content\Audio;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;

require_once __DIR__.'/bootstrap.php';

$platform = PlatformFactory::create(env('GOOGLE_CLOUD_LOCATION'), env('GOOGLE_CLOUD_PROJECT'), adc_aware_http_client());
$model = new Model(Model::GEMINI_2_5_FLASH);

$agent = new Agent($platform, $model, logger: logger());
$messages = new MessageBag(
Message::ofUser(
'What is this recording about?',
Audio::fromFile(dirname(__DIR__, 2).'/fixtures/audio.mp3'),
),
);
$result = $agent->call($messages);

echo $result->getContent().\PHP_EOL;
31 changes: 31 additions & 0 deletions examples/vertexai/bootstrap.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

use Google\Auth\ApplicationDefaultCredentials;
use Psr\Log\LoggerAwareInterface;
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Contracts\HttpClient\HttpClientInterface;

require_once dirname(__DIR__).'/bootstrap.php';

function adc_aware_http_client(): HttpClientInterface
{
$credentials = ApplicationDefaultCredentials::getCredentials(['https://www.googleapis.com/auth/cloud-platform']);
$httpClient = HttpClient::create([
'auth_bearer' => $credentials?->fetchAuthToken()['access_token'] ?? null,
]);

if ($httpClient instanceof LoggerAwareInterface) {
$httpClient->setLogger(logger());
}

return $httpClient;
}
30 changes: 30 additions & 0 deletions examples/vertexai/chat.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\VertexAi\Gemini\Model;
use Symfony\AI\Platform\Bridge\VertexAi\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;

require_once __DIR__.'/bootstrap.php';

$platform = PlatformFactory::create(env('GOOGLE_CLOUD_LOCATION'), env('GOOGLE_CLOUD_PROJECT'), adc_aware_http_client());
$model = new Model(Model::GEMINI_2_5_FLASH);

$agent = new Agent($platform, $model, logger: logger());
$messages = new MessageBag(
Message::forSystem('You are an expert assistant in geography.'),
Message::ofUser('Where is Mount Fuji?'),
);
$result = $agent->call($messages);

echo $result->getContent().\PHP_EOL;
26 changes: 26 additions & 0 deletions examples/vertexai/embeddings.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

use Symfony\AI\Platform\Bridge\VertexAi\Embeddings\Model;
use Symfony\AI\Platform\Bridge\VertexAi\PlatformFactory;

require_once __DIR__.'/bootstrap.php';

$platform = PlatformFactory::create(env('GOOGLE_CLOUD_LOCATION'), env('GOOGLE_CLOUD_PROJECT'), adc_aware_http_client());
$embeddings = new Model();

$result = $platform->invoke($embeddings, <<<TEXT
Once upon a time, there was a country called Japan. It was a beautiful country with a lot of mountains and rivers.
The people of Japan were very kind and hardworking. They loved their country very much and took care of it. The
country was very peaceful and prosperous. The people lived happily ever after.
TEXT);

echo 'Dimensions: '.$result->asVectors()[0]->getDimensions().\PHP_EOL;
34 changes: 34 additions & 0 deletions examples/vertexai/image-input.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\VertexAi\Gemini\Model;
use Symfony\AI\Platform\Bridge\VertexAi\PlatformFactory;
use Symfony\AI\Platform\Message\Content\Image;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;

require_once __DIR__.'/bootstrap.php';

$platform = PlatformFactory::create(env('GOOGLE_CLOUD_LOCATION'), env('GOOGLE_CLOUD_PROJECT'), adc_aware_http_client());
$model = new Model(Model::GEMINI_2_5_PRO);

$agent = new Agent($platform, $model, logger: logger());
$messages = new MessageBag(
Message::forSystem('You are an image analyzer bot that helps identify the content of images.'),
Message::ofUser(
'Describe the image as a comedian would do it.',
Image::fromFile(dirname(__DIR__, 2).'/fixtures/image.jpg'),
),
);
$result = $agent->call($messages);

echo $result->getContent().\PHP_EOL;
33 changes: 33 additions & 0 deletions examples/vertexai/pdf-input-binary.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\VertexAi\Gemini\Model;
use Symfony\AI\Platform\Bridge\VertexAi\PlatformFactory;
use Symfony\AI\Platform\Message\Content\Document;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;

require_once __DIR__.'/bootstrap.php';

$platform = PlatformFactory::create(env('GOOGLE_CLOUD_LOCATION'), env('GOOGLE_CLOUD_PROJECT'), adc_aware_http_client());
$model = new Model(Model::GEMINI_2_5_FLASH);

$agent = new Agent($platform, $model, logger: logger());
$messages = new MessageBag(
Message::ofUser(
Document::fromFile(dirname(__DIR__, 2).'/fixtures/document.pdf'),
'What is this document about?',
),
);
$result = $agent->call($messages);

echo $result->getContent().\PHP_EOL;
38 changes: 38 additions & 0 deletions examples/vertexai/server-tools.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\Toolbox\AgentProcessor;
use Symfony\AI\Agent\Toolbox\Tool\Clock;
use Symfony\AI\Agent\Toolbox\Toolbox;
use Symfony\AI\Platform\Bridge\VertexAi\Gemini\Model;
use Symfony\AI\Platform\Bridge\VertexAi\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;

require_once __DIR__.'/bootstrap.php';

$platform = PlatformFactory::create(env('GOOGLE_CLOUD_LOCATION'), env('GOOGLE_CLOUD_PROJECT'), adc_aware_http_client());

$model = new Model(Model::GEMINI_2_5_PRO);

$toolbox = new Toolbox([new Clock()], logger: logger());
$processor = new AgentProcessor($toolbox);
$agent = new Agent($platform, $model, [$processor], [$processor], logger());

$content = file_get_contents('https://www.euribor-rates.eu/en/current-euribor-rates/4/euribor-rate-12-months/');
$messages = new MessageBag(
Message::ofUser("Based on the following page content, what was the 12-month Euribor rate a week ago?\n\n".$content)
);

$result = $agent->call($messages);

echo $result->getContent().\PHP_EOL;
37 changes: 37 additions & 0 deletions examples/vertexai/stream.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

use Symfony\AI\Agent\Agent;
use Symfony\AI\Platform\Bridge\VertexAi\Gemini\Model;
use Symfony\AI\Platform\Bridge\VertexAi\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;

require_once __DIR__.'/bootstrap.php';

$platform = PlatformFactory::create(env('GOOGLE_CLOUD_LOCATION'), env('GOOGLE_CLOUD_PROJECT'), adc_aware_http_client());
$model = new Model(Model::GEMINI_2_5_FLASH);

$agent = new Agent($platform, $model, logger: logger());
$messages = new MessageBag(
Message::forSystem('You are an expert assistant in geography.'),
Message::ofUser('Where is Mount Fuji?'),
);

$result = $agent->call($messages, [
'stream' => true,
]);

foreach ($result->getContent() as $word) {
echo $word;
}

echo \PHP_EOL;
52 changes: 52 additions & 0 deletions examples/vertexai/structured-output-clock.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\StructuredOutput\AgentProcessor as StructuredOutputProcessor;
use Symfony\AI\Agent\Toolbox\AgentProcessor as ToolProcessor;
use Symfony\AI\Agent\Toolbox\Tool\Clock;
use Symfony\AI\Agent\Toolbox\Toolbox;
use Symfony\AI\Platform\Bridge\VertexAi\Gemini\Model;
use Symfony\AI\Platform\Bridge\VertexAi\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\Component\Clock\Clock as SymfonyClock;

require_once __DIR__.'/bootstrap.php';

$platform = PlatformFactory::create(env('GOOGLE_CLOUD_LOCATION'), env('GOOGLE_CLOUD_PROJECT'), adc_aware_http_client());
$model = new Model(Model::GEMINI_2_5_PRO);

$clock = new Clock(new SymfonyClock());
$toolbox = new Toolbox([$clock]);
$toolProcessor = new ToolProcessor($toolbox);
$structuredOutputProcessor = new StructuredOutputProcessor();
$agent = new Agent($platform, $model, [$toolProcessor, $structuredOutputProcessor], [$toolProcessor, $structuredOutputProcessor], logger());

$messages = new MessageBag(Message::ofUser('What date and time is it?'));
$result = $agent->call($messages, ['response_format' => [
'type' => 'json_schema',
'json_schema' => [
'name' => 'clock',
'strict' => true,
'schema' => [
'type' => 'object',
'properties' => [
'date' => ['type' => 'string', 'description' => 'The current date in the format YYYY-MM-DD.'],
'time' => ['type' => 'string', 'description' => 'The current time in the format HH:MM:SS.'],
],
'required' => ['date', 'time'],
'additionalProperties' => false,
],
],
]]);

dump($result->getContent());
33 changes: 33 additions & 0 deletions examples/vertexai/structured-output-math.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

use Symfony\AI\Agent\Agent;
use Symfony\AI\Agent\StructuredOutput\AgentProcessor;
use Symfony\AI\Fixtures\StructuredOutput\MathReasoning;
use Symfony\AI\Platform\Bridge\VertexAi\Gemini\Model;
use Symfony\AI\Platform\Bridge\VertexAi\PlatformFactory;
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;

require_once __DIR__.'/bootstrap.php';

$platform = PlatformFactory::create(env('GOOGLE_CLOUD_LOCATION'), env('GOOGLE_CLOUD_PROJECT'), adc_aware_http_client());
$model = new Model(Model::GEMINI_2_5_FLASH_LITE);

$processor = new AgentProcessor();
$agent = new Agent($platform, $model, [$processor], [$processor], logger());
$messages = new MessageBag(
Message::forSystem('You are a helpful math tutor. Guide the user through the solution step by step.'),
Message::ofUser('how can I solve 8x + 7 = -23'),
);
$result = $agent->call($messages, ['output_structure' => MathReasoning::class]);

dump($result->getContent());
Loading