From 0e846d24dca7733867b0b00bec10f45205ba35bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Vancoillie?= Date: Fri, 7 Nov 2025 08:39:15 +0100 Subject: [PATCH] feat(aibundle): integrate Albert platform support - Add Albert platform configuration and service definitions. - Make platform factory accept a customizable ModelCatalog instance. --- src/ai-bundle/config/options.php | 10 +++++++++ src/ai-bundle/config/services.php | 2 ++ src/ai-bundle/src/AiBundle.php | 21 +++++++++++++++++++ .../DependencyInjection/AiBundleTest.php | 4 ++++ .../src/Bridge/Albert/PlatformFactory.php | 4 +++- 5 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/ai-bundle/config/options.php b/src/ai-bundle/config/options.php index af08abe5a..3a0968538 100644 --- a/src/ai-bundle/config/options.php +++ b/src/ai-bundle/config/options.php @@ -29,6 +29,16 @@ ->children() ->arrayNode('platform') ->children() + ->arrayNode('albert') + ->children() + ->stringNode('api_key')->isRequired()->end() + ->stringNode('base_url')->isRequired()->end() + ->stringNode('http_client') + ->defaultValue('http_client') + ->info('Service ID of the HTTP client to use') + ->end() + ->end() + ->end() ->arrayNode('anthropic') ->children() ->stringNode('api_key')->isRequired()->end() diff --git a/src/ai-bundle/config/services.php b/src/ai-bundle/config/services.php index 1de2fad69..2e2e44991 100644 --- a/src/ai-bundle/config/services.php +++ b/src/ai-bundle/config/services.php @@ -24,6 +24,7 @@ use Symfony\AI\Chat\Command\DropStoreCommand as DropMessageStoreCommand; use Symfony\AI\Chat\Command\SetupStoreCommand as SetupMessageStoreCommand; use Symfony\AI\Platform\Bridge\AiMlApi\ModelCatalog as AiMlApiModelCatalog; +use Symfony\AI\Platform\Bridge\Albert\ModelCatalog as AlbertModelCatalog; use Symfony\AI\Platform\Bridge\Anthropic\Contract\AnthropicContract; use Symfony\AI\Platform\Bridge\Anthropic\ModelCatalog as AnthropicModelCatalog; use Symfony\AI\Platform\Bridge\Anthropic\TokenOutputProcessor as AnthropicTokenOutputProcessor; @@ -83,6 +84,7 @@ // model catalog ->set('ai.platform.model_catalog.aimlapi', AiMlApiModelCatalog::class) + ->set('ai.platform.model_catalog.albert', AlbertModelCatalog::class) ->set('ai.platform.model_catalog.anthropic', AnthropicModelCatalog::class) ->set('ai.platform.model_catalog.cerebras', CerebrasModelCatalog::class) ->set('ai.platform.model_catalog.deepseek', DeepSeekModelCatalog::class) diff --git a/src/ai-bundle/src/AiBundle.php b/src/ai-bundle/src/AiBundle.php index b96e960b6..d60930c55 100644 --- a/src/ai-bundle/src/AiBundle.php +++ b/src/ai-bundle/src/AiBundle.php @@ -38,6 +38,7 @@ use Symfony\AI\Chat\Bridge\Meilisearch\MessageStore as MeilisearchMessageStore; use Symfony\AI\Chat\Bridge\Pogocache\MessageStore as PogocacheMessageStore; use Symfony\AI\Chat\MessageStoreInterface; +use Symfony\AI\Platform\Bridge\Albert\PlatformFactory as AlbertPlatformFactory; use Symfony\AI\Platform\Bridge\Anthropic\PlatformFactory as AnthropicPlatformFactory; use Symfony\AI\Platform\Bridge\Azure\OpenAi\PlatformFactory as AzureOpenAiPlatformFactory; use Symfony\AI\Platform\Bridge\Cerebras\PlatformFactory as CerebrasPlatformFactory; @@ -246,6 +247,26 @@ public function loadExtension(array $config, ContainerConfigurator $container, C */ private function processPlatformConfig(string $type, array $platform, ContainerBuilder $container): void { + if ('albert' === $type) { + $platformId = 'ai.platform.albert'; + $definition = (new Definition(Platform::class)) + ->setFactory(AlbertPlatformFactory::class.'::create') + ->setLazy(true) + ->addTag('proxy', ['interface' => PlatformInterface::class]) + ->setArguments([ + $platform['api_key'], + $platform['base_url'], + new Reference($platform['http_client'], ContainerInterface::NULL_ON_INVALID_REFERENCE), + new Reference('ai.platform.model_catalog.albert'), + new Reference('event_dispatcher'), + ]) + ->addTag('ai.platform', ['name' => 'albert']); + + $container->setDefinition($platformId, $definition); + + return; + } + if ('anthropic' === $type) { $platformId = 'ai.platform.anthropic'; $definition = (new Definition(Platform::class)) diff --git a/src/ai-bundle/tests/DependencyInjection/AiBundleTest.php b/src/ai-bundle/tests/DependencyInjection/AiBundleTest.php index 4d7438ea4..2bbc3f78b 100644 --- a/src/ai-bundle/tests/DependencyInjection/AiBundleTest.php +++ b/src/ai-bundle/tests/DependencyInjection/AiBundleTest.php @@ -2774,6 +2774,10 @@ private function getFullConfig(): array 'anthropic' => [ 'api_key' => 'anthropic_key_full', ], + 'albert' => [ + 'api_key' => 'albert-test-key', + 'base_url' => 'https://albert.api.etalab.gouv.fr/v1', + ], 'azure' => [ 'my_azure_instance' => [ 'api_key' => 'azure_key_full', diff --git a/src/platform/src/Bridge/Albert/PlatformFactory.php b/src/platform/src/Bridge/Albert/PlatformFactory.php index cde0ee4c5..d83722581 100644 --- a/src/platform/src/Bridge/Albert/PlatformFactory.php +++ b/src/platform/src/Bridge/Albert/PlatformFactory.php @@ -16,6 +16,7 @@ use Symfony\AI\Platform\Bridge\OpenAi\Gpt; use Symfony\AI\Platform\Contract; use Symfony\AI\Platform\Exception\InvalidArgumentException; +use Symfony\AI\Platform\ModelCatalog\ModelCatalogInterface; use Symfony\AI\Platform\Platform; use Symfony\Component\HttpClient\EventSourceHttpClient; use Symfony\Contracts\HttpClient\HttpClientInterface; @@ -29,6 +30,7 @@ public static function create( #[\SensitiveParameter] string $apiKey, string $baseUrl, ?HttpClientInterface $httpClient = null, + ModelCatalogInterface $modelCatalog = new ModelCatalog(), ?EventDispatcherInterface $eventDispatcher = null, ): Platform { if (!str_starts_with($baseUrl, 'https://')) { @@ -52,7 +54,7 @@ public static function create( new EmbeddingsModelClient($httpClient, $apiKey, $baseUrl), ], [new Gpt\ResultConverter(), new Embeddings\ResultConverter()], - new ModelCatalog(), + $modelCatalog, Contract::create(), $eventDispatcher, );