Files
archived-ai/examples/bootstrap.php
2025-10-06 23:32:24 +02:00

202 lines
6.0 KiB
PHP

<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerInterface;
use Symfony\AI\Agent\Exception\ExceptionInterface as AgentException;
use Symfony\AI\Platform\Exception\ExceptionInterface as PlatformException;
use Symfony\AI\Platform\Metadata\Metadata;
use Symfony\AI\Platform\Metadata\TokenUsage;
use Symfony\AI\Platform\Result\ResultPromise;
use Symfony\AI\Store\Exception\ExceptionInterface as StoreException;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Logger\ConsoleLogger;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Contracts\HttpClient\HttpClientInterface;
require_once __DIR__.'/vendor/autoload.php';
(new Dotenv())->loadEnv(__DIR__.'/.env');
function env(string $var): string
{
if (!isset($_SERVER[$var]) || '' === $_SERVER[$var]) {
output()->writeln(sprintf('<error>Please set the "%s" environment variable to run this example.</error>', $var));
exit(1);
}
return $_SERVER[$var];
}
function http_client(): HttpClientInterface
{
$httpClient = HttpClient::create();
if ($httpClient instanceof LoggerAwareInterface) {
$httpClient->setLogger(logger());
}
return $httpClient;
}
function logger(): LoggerInterface
{
$output = output();
return new class($output) extends ConsoleLogger {
private ConsoleOutput $output;
public function __construct(ConsoleOutput $output)
{
parent::__construct($output);
$this->output = $output;
}
/**
* @param Stringable|string $message
*/
public function log($level, $message, array $context = []): void
{
// Call parent to handle the base logging
parent::log($level, $message, $context);
// Add context display for debug verbosity
if ($this->output->getVerbosity() >= ConsoleOutput::VERBOSITY_DEBUG && [] !== $context) {
// Filter out special keys that are already handled
$displayContext = array_filter($context, function ($key) {
return !in_array($key, ['exception', 'error', 'object'], true);
}, \ARRAY_FILTER_USE_KEY);
if ([] !== $displayContext) {
$contextMessage = ' '.json_encode($displayContext, \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE);
$this->output->writeln(sprintf('<comment>%s</comment>', $contextMessage));
}
}
}
};
}
function output(): ConsoleOutput
{
$verbosity = match ($_SERVER['argv'][1] ?? null) {
'-v', '--verbose' => ConsoleOutput::VERBOSITY_VERBOSE,
'-vv', '--very-verbose' => ConsoleOutput::VERBOSITY_VERY_VERBOSE,
'-vvv', '--debug' => ConsoleOutput::VERBOSITY_DEBUG,
default => ConsoleOutput::VERBOSITY_NORMAL,
};
return new ConsoleOutput($verbosity);
}
function print_token_usage(Metadata $metadata): void
{
$tokenUsage = $metadata->get('token_usage');
assert($tokenUsage instanceof TokenUsage);
$na = '<comment>n/a</comment>';
$table = new Table(output());
$table->setHeaderTitle('Token Usage');
$table->setRows([
['Prompt tokens', $tokenUsage->promptTokens ?? $na],
['Completion tokens', $tokenUsage->completionTokens ?? $na],
['Thinking tokens', $tokenUsage->thinkingTokens ?? $na],
['Tool tokens', $tokenUsage->toolTokens ?? $na],
['Cached tokens', $tokenUsage->cachedTokens ?? $na],
['Remaining tokens minute', $tokenUsage->remainingTokensMinute ?? $na],
['Remaining tokens month', $tokenUsage->remainingTokensMonth ?? $na],
['Remaining tokens', $tokenUsage->remainingTokens ?? $na],
['Utilized tokens', $tokenUsage->totalTokens ?? $na],
]);
$table->render();
}
function print_vectors(ResultPromise $result): void
{
assert([] !== $result->asVectors());
assert(array_key_exists(0, $result->asVectors()));
output()->writeln(sprintf('Dimensions: %d', $result->asVectors()[0]->getDimensions()));
}
function perplexity_print_search_results(Metadata $metadata): void
{
$searchResults = $metadata->get('search_results');
if (null === $searchResults) {
return;
}
echo 'Search results:'.\PHP_EOL;
if (0 === count($searchResults)) {
echo 'No search results.'.\PHP_EOL;
return;
}
foreach ($searchResults as $i => $searchResult) {
echo 'Result #'.($i + 1).':'.\PHP_EOL;
echo $searchResult['title'].\PHP_EOL;
echo $searchResult['url'].\PHP_EOL;
echo $searchResult['date'].\PHP_EOL;
echo $searchResult['last_updated'] ? $searchResult['last_updated'].\PHP_EOL : '';
echo $searchResult['snippet'] ? $searchResult['snippet'].\PHP_EOL : '';
echo \PHP_EOL;
}
}
function perplexity_print_citations(Metadata $metadata): void
{
$citations = $metadata->get('citations');
if (null === $citations) {
return;
}
echo 'Citations:'.\PHP_EOL;
if (0 === count($citations)) {
echo 'No citations.'.\PHP_EOL;
return;
}
foreach ($citations as $i => $citation) {
echo 'Citation #'.($i + 1).':'.\PHP_EOL;
echo $citation.\PHP_EOL;
echo \PHP_EOL;
}
}
function print_stream(ResultPromise $result): void
{
foreach ($result->asStream() as $word) {
echo $word;
}
echo \PHP_EOL;
}
set_exception_handler(function ($exception) {
if ($exception instanceof AgentException || $exception instanceof PlatformException || $exception instanceof StoreException) {
output()->writeln(sprintf('<error>%s</error>', $exception->getMessage()));
if (output()->isVerbose()) {
output()->writeln($exception->getTraceAsString());
}
exit(1);
}
throw $exception;
});