|  | 
| 31 | 31 | use Symfony\AI\Agent\Toolbox\ToolFactory\MemoryToolFactory; | 
| 32 | 32 | use Symfony\AI\AiBundle\DependencyInjection\ProcessorCompilerPass; | 
| 33 | 33 | use Symfony\AI\AiBundle\Exception\InvalidArgumentException; | 
|  | 34 | +use Symfony\AI\AiBundle\Profiler\TraceableChat; | 
|  | 35 | +use Symfony\AI\AiBundle\Profiler\TraceableMessageStore; | 
| 34 | 36 | use Symfony\AI\AiBundle\Profiler\TraceablePlatform; | 
| 35 | 37 | use Symfony\AI\AiBundle\Profiler\TraceableToolbox; | 
| 36 | 38 | use Symfony\AI\AiBundle\Security\Attribute\IsGrantedTool; | 
| 37 | 39 | use Symfony\AI\Chat\Bridge\HttpFoundation\SessionStore; | 
| 38 | 40 | use Symfony\AI\Chat\Bridge\Meilisearch\MessageStore as MeilisearchMessageStore; | 
| 39 | 41 | use Symfony\AI\Chat\Bridge\Pogocache\MessageStore as PogocacheMessageStore; | 
|  | 42 | +use Symfony\AI\Chat\Chat; | 
|  | 43 | +use Symfony\AI\Chat\ChatInterface; | 
| 40 | 44 | use Symfony\AI\Chat\MessageStoreInterface; | 
| 41 | 45 | use Symfony\AI\Platform\Bridge\Anthropic\PlatformFactory as AnthropicPlatformFactory; | 
| 42 | 46 | use Symfony\AI\Platform\Bridge\Azure\OpenAi\PlatformFactory as AzureOpenAiPlatformFactory; | 
| @@ -179,11 +183,49 @@ public function loadExtension(array $config, ContainerConfigurator $container, C | 
| 179 | 183 |             $builder->setAlias(MessageStoreInterface::class, reset($messageStores)); | 
| 180 | 184 |         } | 
| 181 | 185 | 
 | 
|  | 186 | +        if ($builder->getParameter('kernel.debug')) { | 
|  | 187 | +            foreach ($messageStores as $messageStore) { | 
|  | 188 | +                $traceableMessageStoreDefinition = (new Definition(TraceableMessageStore::class)) | 
|  | 189 | +                    ->setDecoratedService($messageStore) | 
|  | 190 | +                    ->setArguments([ | 
|  | 191 | +                        new Reference('.inner'), | 
|  | 192 | +                        new Reference(ClockInterface::class), | 
|  | 193 | +                    ]) | 
|  | 194 | +                    ->addTag('ai.traceable_message_store'); | 
|  | 195 | +                $suffix = u($messageStore)->afterLast('.')->toString(); | 
|  | 196 | +                $builder->setDefinition('ai.traceable_message_store.'.$suffix, $traceableMessageStoreDefinition); | 
|  | 197 | +            } | 
|  | 198 | +        } | 
|  | 199 | + | 
| 182 | 200 |         if ([] === $messageStores) { | 
| 183 | 201 |             $builder->removeDefinition('ai.command.setup_message_store'); | 
| 184 | 202 |             $builder->removeDefinition('ai.command.drop_message_store'); | 
| 185 | 203 |         } | 
| 186 | 204 | 
 | 
|  | 205 | +        foreach ($config['chat'] ?? [] as $name => $chat) { | 
|  | 206 | +            $this->processChatConfig($name, $chat, $builder); | 
|  | 207 | +        } | 
|  | 208 | + | 
|  | 209 | +        $chats = array_keys($builder->findTaggedServiceIds('ai.chat')); | 
|  | 210 | + | 
|  | 211 | +        if (1 === \count($chats)) { | 
|  | 212 | +            $builder->setAlias(ChatInterface::class, reset($chats)); | 
|  | 213 | +        } | 
|  | 214 | + | 
|  | 215 | +        if ($builder->getParameter('kernel.debug')) { | 
|  | 216 | +            foreach ($chats as $chat) { | 
|  | 217 | +                $traceableChatDefinition = (new Definition(TraceableChat::class)) | 
|  | 218 | +                    ->setDecoratedService($chat) | 
|  | 219 | +                    ->setArguments([ | 
|  | 220 | +                        new Reference('.inner'), | 
|  | 221 | +                        new Reference(ClockInterface::class), | 
|  | 222 | +                    ]) | 
|  | 223 | +                    ->addTag('ai.traceable_chat'); | 
|  | 224 | +                $suffix = u($chat)->afterLast('.')->toString(); | 
|  | 225 | +                $builder->setDefinition('ai.traceable_chat.'.$suffix, $traceableChatDefinition); | 
|  | 226 | +            } | 
|  | 227 | +        } | 
|  | 228 | + | 
| 187 | 229 |         foreach ($config['vectorizer'] ?? [] as $vectorizerName => $vectorizer) { | 
| 188 | 230 |             $this->processVectorizerConfig($vectorizerName, $vectorizer, $builder); | 
| 189 | 231 |         } | 
| @@ -1396,6 +1438,26 @@ private function processMessageStoreConfig(string $type, array $messageStores, C | 
| 1396 | 1438 |         } | 
| 1397 | 1439 |     } | 
| 1398 | 1440 | 
 | 
|  | 1441 | +    /** | 
|  | 1442 | +     * @param array{ | 
|  | 1443 | +     *     agent: string, | 
|  | 1444 | +     *     message_store: string, | 
|  | 1445 | +     * } $configuration | 
|  | 1446 | +     */ | 
|  | 1447 | +    private function processChatConfig(string $name, array $configuration, ContainerBuilder $container): void | 
|  | 1448 | +    { | 
|  | 1449 | +        $definition = new Definition(Chat::class); | 
|  | 1450 | +        $definition | 
|  | 1451 | +            ->setArguments([ | 
|  | 1452 | +                new Reference($configuration['agent']), | 
|  | 1453 | +                new Reference($configuration['message_store']), | 
|  | 1454 | +            ]) | 
|  | 1455 | +            ->addTag('ai.chat'); | 
|  | 1456 | + | 
|  | 1457 | +        $container->setDefinition('ai.chat.'.$name, $definition); | 
|  | 1458 | +        $container->registerAliasForArgument('ai.chat.'.$name, ChatInterface::class, $name); | 
|  | 1459 | +    } | 
|  | 1460 | + | 
| 1399 | 1461 |     /** | 
| 1400 | 1462 |      * @param array<string, mixed> $config | 
| 1401 | 1463 |      */ | 
|  | 
0 commit comments