Skip to content

Commit bb1e00a

Browse files
committed
feature #50 feat: Google structured output (valtzu)
This PR was merged into the main branch. Discussion ---------- feat: Google structured output | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | Docs? | no | Issues | | License | MIT Cherry picking php-llm/llm-chain#354 Commits ------- 0a0e632 feat: Google structured output (#354)
2 parents e239ecc + 0a0e632 commit bb1e00a

File tree

4 files changed

+106
-0
lines changed

4 files changed

+106
-0
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
use Symfony\AI\Agent\Agent;
13+
use Symfony\AI\Agent\StructuredOutput\AgentProcessor as StructuredOutputProcessor;
14+
use Symfony\AI\Agent\Toolbox\AgentProcessor as ToolProcessor;
15+
use Symfony\AI\Agent\Toolbox\Tool\Clock;
16+
use Symfony\AI\Agent\Toolbox\Toolbox;
17+
use Symfony\AI\Platform\Bridge\Google\Gemini;
18+
use Symfony\AI\Platform\Bridge\Google\PlatformFactory;
19+
use Symfony\AI\Platform\Message\Message;
20+
use Symfony\AI\Platform\Message\MessageBag;
21+
use Symfony\Component\Clock\Clock as SymfonyClock;
22+
use Symfony\Component\Dotenv\Dotenv;
23+
24+
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
25+
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
26+
27+
if (empty($_ENV['GOOGLE_API_KEY'])) {
28+
echo 'Please set the GOOGLE_API_KEY environment variable.'.\PHP_EOL;
29+
exit(1);
30+
}
31+
32+
$platform = PlatformFactory::create($_ENV['GOOGLE_API_KEY']);
33+
$model = new Gemini(Gemini::GEMINI_1_5_FLASH);
34+
35+
$clock = new Clock(new SymfonyClock());
36+
$toolbox = Toolbox::create($clock);
37+
$toolProcessor = new ToolProcessor($toolbox);
38+
$structuredOutputProcessor = new StructuredOutputProcessor();
39+
$agent = new Agent($platform, $model, [$toolProcessor, $structuredOutputProcessor], [$toolProcessor, $structuredOutputProcessor]);
40+
41+
$messages = new MessageBag(Message::ofUser('What date and time is it?'));
42+
$response = $agent->call($messages, ['response_format' => [
43+
'type' => 'json_schema',
44+
'json_schema' => [
45+
'name' => 'clock',
46+
'strict' => true,
47+
'schema' => [
48+
'type' => 'object',
49+
'properties' => [
50+
'date' => ['type' => 'string', 'description' => 'The current date in the format YYYY-MM-DD.'],
51+
'time' => ['type' => 'string', 'description' => 'The current time in the format HH:MM:SS.'],
52+
],
53+
'required' => ['date', 'time'],
54+
'additionalProperties' => false,
55+
],
56+
],
57+
]]);
58+
59+
dump($response->getContent());
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
use Symfony\AI\Agent\Agent;
13+
use Symfony\AI\Agent\StructuredOutput\AgentProcessor;
14+
use Symfony\AI\Fixtures\StructuredOutput\MathReasoning;
15+
use Symfony\AI\Platform\Bridge\Google\Gemini;
16+
use Symfony\AI\Platform\Bridge\Google\PlatformFactory;
17+
use Symfony\AI\Platform\Message\Message;
18+
use Symfony\AI\Platform\Message\MessageBag;
19+
use Symfony\Component\Dotenv\Dotenv;
20+
21+
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
22+
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
23+
24+
if (empty($_ENV['GOOGLE_API_KEY'])) {
25+
echo 'Please set the GOOGLE_API_KEY environment variable.'.\PHP_EOL;
26+
exit(1);
27+
}
28+
29+
$platform = PlatformFactory::create($_ENV['GOOGLE_API_KEY']);
30+
$model = new Gemini(Gemini::GEMINI_1_5_FLASH);
31+
32+
$processor = new AgentProcessor();
33+
$agent = new Agent($platform, $model, [$processor], [$processor]);
34+
$messages = new MessageBag(
35+
Message::forSystem('You are a helpful math tutor. Guide the user through the solution step by step.'),
36+
Message::ofUser('how can I solve 8x + 7 = -23'),
37+
);
38+
$response = $agent->call($messages, ['output_structure' => MathReasoning::class]);
39+
40+
dump($response->getContent());

src/platform/src/Bridge/Google/Gemini.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public function __construct(string $name = self::GEMINI_2_PRO, array $options =
3636
Capability::INPUT_AUDIO,
3737
Capability::INPUT_PDF,
3838
Capability::OUTPUT_STREAMING,
39+
Capability::OUTPUT_STRUCTURED,
3940
Capability::TOOL_CALLING,
4041
];
4142

src/platform/src/Bridge/Google/ModelHandler.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ public function request(Model $model, array|string $payload, array $options = []
6161
$options['stream'] ?? false ? 'streamGenerateContent' : 'generateContent',
6262
);
6363

64+
if (isset($options['response_format']['json_schema']['schema'])) {
65+
$options['responseMimeType'] = 'application/json';
66+
$options['responseJsonSchema'] = $options['response_format']['json_schema']['schema'];
67+
unset($options['response_format']);
68+
}
69+
6470
$generationConfig = ['generationConfig' => $options];
6571
unset($generationConfig['generationConfig']['stream']);
6672
unset($generationConfig['generationConfig']['tools']);

0 commit comments

Comments
 (0)