diff --git a/examples/albert/_model-listing.php b/examples/albert/_model-listing.php new file mode 100644 index 000000000..1db3d1f86 --- /dev/null +++ b/examples/albert/_model-listing.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\AI\Platform\Bridge\Albert\ApiClient; +use Symfony\AI\Platform\Model; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\SingleCommandApplication; +use Symfony\Component\Console\Style\SymfonyStyle; + +require_once dirname(__DIR__).'/bootstrap.php'; + +$app = (new SingleCommandApplication('Albert API Model Listing')) + ->setDescription('Lists all available models on Albert API') + ->setCode(function (InputInterface $input, OutputInterface $output) { + $io = new SymfonyStyle($input, $output); + $io->title('Albert API Model Listing'); + + $apiClient = new ApiClient(env('ALBERT_API_URL'), env('ALBERT_API_KEY'), http_client()); + $models = $apiClient->getModels(); + + if (0 === count($models)) { + $io->error('No models found for this Albert API URL.'); + + return Command::FAILURE; + } + + $io->listing( + array_map(fn (Model $model) => $model->getName(), $models) + ); + + return Command::SUCCESS; + }) + ->run(); diff --git a/examples/albert/chat.php b/examples/albert/chat.php index dd7e42747..a420da755 100644 --- a/examples/albert/chat.php +++ b/examples/albert/chat.php @@ -36,9 +36,9 @@ 'Use the provided context to answer questions accurately.' ), Message::ofUser($documentContext), - Message::ofUser('What are the main objectives of France\'s AI strategy?'), + Message::ofUser('Summarize the main objectives of France\'s AI strategy in one sentence.'), ); -$result = $platform->invoke('llama-3.3-70b-instruct', $messages); +$result = $platform->invoke('albert-small', $messages); echo $result->asText().\PHP_EOL; diff --git a/examples/albert/embeddings.php b/examples/albert/embeddings.php new file mode 100644 index 000000000..dff0d611d --- /dev/null +++ b/examples/albert/embeddings.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\AI\Platform\Bridge\Albert\PlatformFactory; + +require_once dirname(__DIR__).'/bootstrap.php'; + +$platform = PlatformFactory::create(env('ALBERT_API_KEY'), env('ALBERT_API_URL'), http_client()); + +$response = $platform->invoke('embeddings-small', <<asVectors()[0]->getDimensions().\PHP_EOL; diff --git a/src/platform/src/Bridge/Albert/ApiClient.php b/src/platform/src/Bridge/Albert/ApiClient.php new file mode 100644 index 000000000..daca65b9f --- /dev/null +++ b/src/platform/src/Bridge/Albert/ApiClient.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\AI\Platform\Bridge\Albert; + +use Symfony\AI\Platform\Model; +use Symfony\Component\HttpClient\HttpClient; +use Symfony\Contracts\HttpClient\HttpClientInterface; + +/** + * @author Christopher Hertel + */ +final class ApiClient +{ + public function __construct( + private readonly string $apiUrl, + #[\SensitiveParameter] private readonly string $apiKey, + private ?HttpClientInterface $httpClient = null, + ) { + $this->httpClient = $httpClient ?? HttpClient::create(); + } + + /** + * @return Model[] + */ + public function getModels(): array + { + $result = $this->httpClient->request('GET', \sprintf('%s/models', $this->apiUrl), [ + 'auth_bearer' => $this->apiKey, + ]); + + return array_map(fn (array $model) => new Model($model['id']), $result->toArray()['data']); + } +} diff --git a/src/platform/src/Bridge/Albert/ModelCatalog.php b/src/platform/src/Bridge/Albert/ModelCatalog.php index 62e4833bf..d57e2ba52 100644 --- a/src/platform/src/Bridge/Albert/ModelCatalog.php +++ b/src/platform/src/Bridge/Albert/ModelCatalog.php @@ -11,6 +11,7 @@ namespace Symfony\AI\Platform\Bridge\Albert; +use Symfony\AI\Platform\Bridge\OpenAi\Embeddings; use Symfony\AI\Platform\Bridge\OpenAi\Gpt; use Symfony\AI\Platform\Capability; use Symfony\AI\Platform\Model; @@ -44,11 +45,8 @@ public function __construct(array $additionalModels = []) ], ], 'embeddings-small' => [ - 'class' => Gpt::class, - 'capabilities' => [ - Capability::INPUT_MESSAGES, - Capability::OUTPUT_STRUCTURED, - ], + 'class' => Embeddings::class, + 'capabilities' => [Capability::INPUT_TEXT], ], ]; diff --git a/src/platform/tests/Bridge/Albert/ModelCatalogTest.php b/src/platform/tests/Bridge/Albert/ModelCatalogTest.php index d1eb41f7b..ff8b610dd 100644 --- a/src/platform/tests/Bridge/Albert/ModelCatalogTest.php +++ b/src/platform/tests/Bridge/Albert/ModelCatalogTest.php @@ -12,6 +12,7 @@ namespace Symfony\AI\Platform\Tests\Bridge\Albert; use Symfony\AI\Platform\Bridge\Albert\ModelCatalog; +use Symfony\AI\Platform\Bridge\OpenAi\Embeddings; use Symfony\AI\Platform\Bridge\OpenAi\Gpt; use Symfony\AI\Platform\Capability; use Symfony\AI\Platform\ModelCatalog\ModelCatalogInterface; @@ -26,7 +27,7 @@ public static function modelsProvider(): iterable { yield 'albert-small' => ['albert-small', Gpt::class, [Capability::INPUT_MESSAGES, Capability::OUTPUT_TEXT, Capability::OUTPUT_STREAMING]]; yield 'albert-large' => ['albert-large', Gpt::class, [Capability::INPUT_MESSAGES, Capability::OUTPUT_TEXT, Capability::OUTPUT_STREAMING]]; - yield 'embeddings-small' => ['embeddings-small', Gpt::class, [Capability::INPUT_MESSAGES, Capability::OUTPUT_STRUCTURED]]; + yield 'embeddings-small' => ['embeddings-small', Embeddings::class, [Capability::INPUT_TEXT]]; } protected function createModelCatalog(): ModelCatalogInterface