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

Commit b2b684e

Browse files
committed
feat: expose Gemini grounding metadata
1 parent cb6fc83 commit b2b684e

File tree

2 files changed

+88
-0
lines changed

2 files changed

+88
-0
lines changed

examples/google/grounding.php

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
use PhpLlm\LlmChain\Chain\Chain;
4+
use PhpLlm\LlmChain\Chain\Toolbox\ChainProcessor;
5+
use PhpLlm\LlmChain\Chain\Toolbox\Tool\Clock;
6+
use PhpLlm\LlmChain\Chain\Toolbox\Toolbox;
7+
use PhpLlm\LlmChain\Platform\Bridge\Google\Gemini;
8+
use PhpLlm\LlmChain\Platform\Bridge\Google\GroundingOutputProcessor;
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\Dotenv\Dotenv;
13+
14+
require_once dirname(__DIR__, 2).'/vendor/autoload.php';
15+
(new Dotenv())->loadEnv(dirname(__DIR__, 2).'/.env');
16+
17+
if (!$_ENV['GEMINI_API_KEY']) {
18+
echo 'Please set the GEMINI_API_KEY environment variable.'.\PHP_EOL;
19+
exit(1);
20+
}
21+
22+
$platform = PlatformFactory::create($_ENV['GEMINI_API_KEY']);
23+
24+
// Available server-side tools as of 2025-06-28: url_context, google_search, code_execution
25+
$llm = new Gemini('gemini-2.5-pro-preview-03-25', ['server_tools' => ['google_search' => true], 'temperature' => 1.0]);
26+
27+
$toolbox = Toolbox::create(new Clock());
28+
$processor = new ChainProcessor($toolbox);
29+
$chain = new Chain($platform, $llm, outputProcessors: [new GroundingOutputProcessor()]);
30+
31+
$messages = new MessageBag(Message::ofUser('Summarize what is Symfony framework in 3 sentences'));
32+
33+
$response = $chain->call($messages);
34+
35+
echo $response->getContent().\PHP_EOL;
36+
37+
$metadata = $response->getMetadata()['grounding'];
38+
39+
printf(
40+
<<<'FORMAT'
41+
Search queries: %s
42+
Sources: %s
43+
44+
FORMAT,
45+
implode(', ', $metadata['webSearchQueries']),
46+
implode(', ', array_unique(array_column(array_column($metadata['groundingChunks'], 'web'), 'title')))
47+
);
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpLlm\LlmChain\Platform\Bridge\Google;
6+
7+
use PhpLlm\LlmChain\Chain\Output;
8+
use PhpLlm\LlmChain\Chain\OutputProcessorInterface;
9+
use PhpLlm\LlmChain\Platform\Response\StreamResponse;
10+
use Symfony\Contracts\HttpClient\ResponseInterface;
11+
12+
/**
13+
* Adds grounding metadata from Google Search / URL context.
14+
*
15+
* @author Valtteri R <[email protected]>
16+
*/
17+
final class GroundingOutputProcessor implements OutputProcessorInterface
18+
{
19+
public function processOutput(Output $output): void
20+
{
21+
if ($output->response instanceof StreamResponse) {
22+
// Streams have to be handled manually as the tokens are part of the streamed chunks
23+
return;
24+
}
25+
26+
$rawResponse = $output->response->getRawResponse()?->getRawObject();
27+
if (!$rawResponse instanceof ResponseInterface) {
28+
return;
29+
}
30+
31+
$metadata = $output->response->getMetadata();
32+
33+
$content = $rawResponse->toArray(false);
34+
35+
if (!$grounding = $content['candidates'][0]['groundingMetadata'] ?? null) {
36+
return;
37+
}
38+
39+
$metadata->add('grounding', $grounding);
40+
}
41+
}

0 commit comments

Comments
 (0)