Skip to content
This repository was archived by the owner on Jul 16, 2025. It is now read-only.

Commit 439953c

Browse files
authored
feat: Google structured output (#354)
1 parent 97982eb commit 439953c

File tree

4 files changed

+88
-0
lines changed

4 files changed

+88
-0
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
use PhpLlm\LlmChain\Chain\Chain;
4+
use PhpLlm\LlmChain\Chain\StructuredOutput\ChainProcessor as StructuredOutputProcessor;
5+
use PhpLlm\LlmChain\Chain\Toolbox\ChainProcessor as ToolProcessor;
6+
use PhpLlm\LlmChain\Chain\Toolbox\Tool\Clock;
7+
use PhpLlm\LlmChain\Chain\Toolbox\Toolbox;
8+
use PhpLlm\LlmChain\Platform\Bridge\Google\Gemini;
9+
use PhpLlm\LlmChain\Platform\Bridge\Google\PlatformFactory;
10+
use PhpLlm\LlmChain\Platform\Message\Message;
11+
use PhpLlm\LlmChain\Platform\Message\MessageBag;
12+
use Symfony\Component\Clock\Clock as SymfonyClock;
13+
use Symfony\Component\Dotenv\Dotenv;
14+
15+
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
16+
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
17+
18+
if (empty($_ENV['GOOGLE_API_KEY'])) {
19+
echo 'Please set the GOOGLE_API_KEY environment variable.'.\PHP_EOL;
20+
exit(1);
21+
}
22+
23+
$platform = PlatformFactory::create($_ENV['GOOGLE_API_KEY']);
24+
$model = new Gemini(Gemini::GEMINI_1_5_FLASH);
25+
26+
$clock = new Clock(new SymfonyClock());
27+
$toolbox = Toolbox::create($clock);
28+
$toolProcessor = new ToolProcessor($toolbox);
29+
$structuredOutputProcessor = new StructuredOutputProcessor();
30+
$chain = new Chain($platform, $model, [$toolProcessor, $structuredOutputProcessor], [$toolProcessor, $structuredOutputProcessor]);
31+
32+
$messages = new MessageBag(Message::ofUser('What date and time is it?'));
33+
$response = $chain->call($messages, ['response_format' => [
34+
'type' => 'json_schema',
35+
'json_schema' => [
36+
'name' => 'clock',
37+
'strict' => true,
38+
'schema' => [
39+
'type' => 'object',
40+
'properties' => [
41+
'date' => ['type' => 'string', 'description' => 'The current date in the format YYYY-MM-DD.'],
42+
'time' => ['type' => 'string', 'description' => 'The current time in the format HH:MM:SS.'],
43+
],
44+
'required' => ['date', 'time'],
45+
'additionalProperties' => false,
46+
],
47+
],
48+
]]);
49+
50+
dump($response->getContent());
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
use PhpLlm\LlmChain\Chain\Chain;
4+
use PhpLlm\LlmChain\Chain\StructuredOutput\ChainProcessor;
5+
use PhpLlm\LlmChain\Platform\Bridge\Google\Gemini;
6+
use PhpLlm\LlmChain\Platform\Bridge\Google\PlatformFactory;
7+
use PhpLlm\LlmChain\Platform\Message\Message;
8+
use PhpLlm\LlmChain\Platform\Message\MessageBag;
9+
use PhpLlm\LlmChain\Tests\Fixture\StructuredOutput\MathReasoning;
10+
use Symfony\Component\Dotenv\Dotenv;
11+
12+
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
13+
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
14+
15+
if (empty($_ENV['GOOGLE_API_KEY'])) {
16+
echo 'Please set the GOOGLE_API_KEY environment variable.'.\PHP_EOL;
17+
exit(1);
18+
}
19+
20+
$platform = PlatformFactory::create($_ENV['GOOGLE_API_KEY']);
21+
$model = new Gemini(Gemini::GEMINI_1_5_FLASH);
22+
23+
$processor = new ChainProcessor();
24+
$chain = new Chain($platform, $model, [$processor], [$processor]);
25+
$messages = new MessageBag(
26+
Message::forSystem('You are a helpful math tutor. Guide the user through the solution step by step.'),
27+
Message::ofUser('how can I solve 8x + 7 = -23'),
28+
);
29+
$response = $chain->call($messages, ['output_structure' => MathReasoning::class]);
30+
31+
dump($response->getContent());

src/Platform/Bridge/Google/Gemini.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public function __construct(string $name = self::GEMINI_2_PRO, array $options =
2929
Capability::INPUT_AUDIO,
3030
Capability::INPUT_PDF,
3131
Capability::OUTPUT_STREAMING,
32+
Capability::OUTPUT_STRUCTURED,
3233
Capability::TOOL_CALLING,
3334
];
3435

src/Platform/Bridge/Google/ModelHandler.php

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

57+
if (isset($options['response_format']['json_schema']['schema'])) {
58+
$options['responseMimeType'] = 'application/json';
59+
$options['responseJsonSchema'] = $options['response_format']['json_schema']['schema'];
60+
unset($options['response_format']);
61+
}
62+
5763
$generationConfig = ['generationConfig' => $options];
5864
unset($generationConfig['generationConfig']['stream']);
5965
unset($generationConfig['generationConfig']['tools']);

0 commit comments

Comments
 (0)