14
14
use Google \Auth \ApplicationDefaultCredentials ;
15
15
use Symfony \AI \Agent \Agent ;
16
16
use Symfony \AI \Agent \AgentInterface ;
17
+ use Symfony \AI \Agent \Attribute \AsInputProcessor ;
18
+ use Symfony \AI \Agent \Attribute \AsOutputProcessor ;
17
19
use Symfony \AI \Agent \InputProcessor \SystemPromptInputProcessor ;
18
20
use Symfony \AI \Agent \InputProcessorInterface ;
19
21
use Symfony \AI \Agent \OutputProcessorInterface ;
22
24
use Symfony \AI \Agent \Toolbox \Tool \Agent as AgentTool ;
23
25
use Symfony \AI \Agent \Toolbox \ToolFactory \ChainFactory ;
24
26
use Symfony \AI \Agent \Toolbox \ToolFactory \MemoryToolFactory ;
27
+ use Symfony \AI \AiBundle \DependencyInjection \ProcessorCompilerPass ;
25
28
use Symfony \AI \AiBundle \Exception \InvalidArgumentException ;
26
29
use Symfony \AI \AiBundle \Profiler \TraceablePlatform ;
27
30
use Symfony \AI \AiBundle \Profiler \TraceableToolbox ;
83
86
*/
84
87
final class AiBundle extends AbstractBundle
85
88
{
89
+ public function build (ContainerBuilder $ container )
90
+ {
91
+ parent ::build ($ container );
92
+
93
+ $ container ->addCompilerPass (new ProcessorCompilerPass ());
94
+ }
95
+
86
96
public function configure (DefinitionConfigurator $ definition ): void
87
97
{
88
98
$ definition ->import ('../config/options.php ' );
@@ -143,10 +153,25 @@ public function loadExtension(array $config, ContainerConfigurator $container, C
143
153
]);
144
154
});
145
155
156
+ $ builder ->registerAttributeForAutoconfiguration (AsInputProcessor::class, static function (ChildDefinition $ definition , AsInputProcessor $ attribute ): void {
157
+ $ definition ->addTag ('ai.agent.input_processor ' , [
158
+ 'agent ' => $ attribute ->agent ,
159
+ 'priority ' => $ attribute ->priority ,
160
+ ]);
161
+ });
162
+
163
+ $ builder ->registerAttributeForAutoconfiguration (AsOutputProcessor::class, static function (ChildDefinition $ definition , AsOutputProcessor $ attribute ): void {
164
+ $ definition ->addTag ('ai.agent.output_processor ' , [
165
+ 'agent ' => $ attribute ->agent ,
166
+ 'priority ' => $ attribute ->priority ,
167
+ ]);
168
+ });
169
+
146
170
$ builder ->registerForAutoconfiguration (InputProcessorInterface::class)
147
- ->addTag ('ai.agent.input_processor ' );
171
+ ->addTag ('ai.agent.input_processor ' , [ ' tagged_by ' => ' interface ' ] );
148
172
$ builder ->registerForAutoconfiguration (OutputProcessorInterface::class)
149
- ->addTag ('ai.agent.output_processor ' );
173
+ ->addTag ('ai.agent.output_processor ' , ['tagged_by ' => 'interface ' ]);
174
+
150
175
$ builder ->registerForAutoconfiguration (ModelClientInterface::class)
151
176
->addTag ('ai.platform.model_client ' );
152
177
$ builder ->registerForAutoconfiguration (ResultConverterInterface::class)
@@ -436,9 +461,6 @@ private function processAgentConfig(string $name, array $config, ContainerBuilde
436
461
->setArgument (0 , new Reference ($ config ['platform ' ]))
437
462
->setArgument (1 , new Reference ('ai.agent. ' .$ name .'.model ' ));
438
463
439
- $ inputProcessors = [];
440
- $ outputProcessors = [];
441
-
442
464
// TOOL & PROCESSOR
443
465
if ($ config ['tools ' ]['enabled ' ]) {
444
466
// Create specific toolbox and process if tools are explicitly defined
@@ -492,26 +514,28 @@ private function processAgentConfig(string $name, array $config, ContainerBuilde
492
514
493
515
$ toolProcessorDefinition = (new ChildDefinition ('ai.tool.agent_processor.abstract ' ))
494
516
->replaceArgument (0 , new Reference ('ai.toolbox. ' .$ name ));
495
- $ container ->setDefinition ('ai.tool.agent_processor. ' .$ name , $ toolProcessorDefinition );
496
517
497
- $ inputProcessors [] = new Reference ('ai.tool.agent_processor. ' .$ name );
498
- $ outputProcessors [] = new Reference ('ai.tool.agent_processor. ' .$ name );
518
+ $ container ->setDefinition ('ai.tool.agent_processor. ' .$ name , $ toolProcessorDefinition )
519
+ ->addTag ('ai.agent.input_processor ' , ['agent ' => $ name , 'priority ' => -10 ])
520
+ ->addTag ('ai.agent.output_processor ' , ['agent ' => $ name , 'priority ' => -10 ]);
499
521
} else {
500
522
if ($ config ['fault_tolerant_toolbox ' ] && !$ container ->hasDefinition ('ai.fault_tolerant_toolbox ' )) {
501
523
$ container ->setDefinition ('ai.fault_tolerant_toolbox ' , new Definition (FaultTolerantToolbox::class))
502
524
->setArguments ([new Reference ('.inner ' )])
503
525
->setDecoratedService ('ai.toolbox ' );
504
526
}
505
527
506
- $ inputProcessors [] = new Reference ('ai.tool.agent_processor ' );
507
- $ outputProcessors [] = new Reference ('ai.tool.agent_processor ' );
528
+ $ container ->getDefinition ('ai.tool.agent_processor ' )
529
+ ->addTag ('ai.agent.input_processor ' , ['agent ' => $ name , 'priority ' => -10 ])
530
+ ->addTag ('ai.agent.output_processor ' , ['agent ' => $ name , 'priority ' => -10 ]);
508
531
}
509
532
}
510
533
511
534
// STRUCTURED OUTPUT
512
535
if ($ config ['structured_output ' ]) {
513
- $ inputProcessors [] = new Reference ('ai.agent.structured_output_processor ' );
514
- $ outputProcessors [] = new Reference ('ai.agent.structured_output_processor ' );
536
+ $ container ->getDefinition ('ai.agent.structured_output_processor ' )
537
+ ->addTag ('ai.agent.input_processor ' , ['agent ' => $ name , 'priority ' => -20 ])
538
+ ->addTag ('ai.agent.output_processor ' , ['agent ' => $ name , 'priority ' => -20 ]);
515
539
}
516
540
517
541
// TOKEN USAGE TRACKING
@@ -530,25 +554,28 @@ private function processAgentConfig(string $name, array $config, ContainerBuilde
530
554
}
531
555
532
556
if ($ container ->hasDefinition ('ai.platform.token_usage_processor. ' .$ platform )) {
533
- $ outputProcessors [] = new Reference ('ai.platform.token_usage_processor. ' .$ platform );
557
+ $ container ->getDefinition ('ai.platform.token_usage_processor. ' .$ platform )
558
+ ->addTag ('ai.agent.output_processor ' , ['agent ' => $ name , 'priority ' => -30 ]);
534
559
}
535
560
}
536
561
}
537
562
538
563
// SYSTEM PROMPT
539
564
if (\is_string ($ config ['system_prompt ' ])) {
540
- $ systemPromptInputProcessorDefinition = new Definition (SystemPromptInputProcessor::class, [
541
- $ config ['system_prompt ' ],
542
- $ config ['include_tools ' ] ? new Reference ('ai.toolbox. ' .$ name ) : null ,
543
- new Reference ('logger ' , ContainerInterface::IGNORE_ON_INVALID_REFERENCE ),
544
- ]);
565
+ $ systemPromptInputProcessorDefinition = (new Definition (SystemPromptInputProcessor::class))
566
+ ->setArguments ([
567
+ $ config ['system_prompt ' ],
568
+ $ config ['include_tools ' ] ? new Reference ('ai.toolbox. ' .$ name ) : null ,
569
+ new Reference ('logger ' , ContainerInterface::IGNORE_ON_INVALID_REFERENCE ),
570
+ ])
571
+ ->addTag ('ai.agent.input_processor ' , ['agent ' => $ name , 'priority ' => -30 ]);
545
572
546
- $ inputProcessors [] = $ systemPromptInputProcessorDefinition ;
573
+ $ container -> setDefinition ( ' ai.agent. ' . $ name . ' .system_prompt_processor ' , $ systemPromptInputProcessorDefinition) ;
547
574
}
548
575
549
576
$ agentDefinition
550
- ->setArgument (2 , $ inputProcessors )
551
- ->setArgument (3 , $ outputProcessors )
577
+ ->setArgument (2 , []) // placeholder until ProcessorCompilerPass process.
578
+ ->setArgument (3 , []) // placeholder until ProcessorCompilerPass process.
552
579
->setArgument (4 , new Reference ('logger ' , ContainerInterface::IGNORE_ON_INVALID_REFERENCE ))
553
580
;
554
581
0 commit comments