Skip to content

Commit 33f3170

Browse files
VincentLangletdevmatt000
authored andcommitted
[Agent] Allow translatable prompts in SystemPromptInputProcessor
1 parent b142198 commit 33f3170

File tree

6 files changed

+31
-25
lines changed

6 files changed

+31
-25
lines changed

src/agent/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
"symfony/dom-crawler": "^7.3|^8.0",
4343
"symfony/event-dispatcher": "^7.3|^8.0",
4444
"symfony/http-foundation": "^7.3|^8.0",
45+
"symfony/translation": "^7.3|^8.0",
4546
"symfony/translation-contracts": "^3.6"
4647
},
4748
"autoload": {

src/agent/src/InputProcessor/SystemPromptInputProcessor.php

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Symfony\AI\Agent\Toolbox\ToolboxInterface;
2020
use Symfony\AI\Platform\Message\Message;
2121
use Symfony\AI\Platform\Tool\Tool;
22+
use Symfony\Contracts\Translation\TranslatableInterface;
2223
use Symfony\Contracts\Translation\TranslatorInterface;
2324

2425
/**
@@ -27,19 +28,17 @@
2728
final readonly class SystemPromptInputProcessor implements InputProcessorInterface
2829
{
2930
/**
30-
* @param \Stringable|string $systemPrompt the system prompt to prepend to the input messages
31-
* @param ToolboxInterface|null $toolbox the tool box to be used to append the tool definitions to the system prompt
31+
* @param \Stringable|TranslatableInterface|string $systemPrompt the system prompt to prepend to the input messages
32+
* @param ToolboxInterface|null $toolbox the tool box to be used to append the tool definitions to the system prompt
3233
*/
3334
public function __construct(
34-
private \Stringable|string $systemPrompt,
35+
private \Stringable|TranslatableInterface|string $systemPrompt,
3536
private ?ToolboxInterface $toolbox = null,
3637
private ?TranslatorInterface $translator = null,
37-
private bool $enableTranslation = false,
38-
private ?string $translationDomain = null,
3938
private LoggerInterface $logger = new NullLogger(),
4039
) {
41-
if ($this->enableTranslation && !$this->translator) {
42-
throw new RuntimeException('Prompt translation is enabled but no translator was provided.');
40+
if ($this->systemPrompt instanceof TranslatableInterface && !$this->translator) {
41+
throw new RuntimeException('Translatable system prompt is not supported when no translator is provided.');
4342
}
4443
}
4544

@@ -53,8 +52,8 @@ public function processInput(Input $input): void
5352
return;
5453
}
5554

56-
$message = $this->enableTranslation
57-
? $this->translator->trans((string) $this->systemPrompt, [], $this->translationDomain)
55+
$message = $this->systemPrompt instanceof TranslatableInterface
56+
? $this->systemPrompt->trans($this->translator)
5857
: (string) $this->systemPrompt;
5958

6059
if ($this->toolbox instanceof ToolboxInterface

src/agent/tests/InputProcessor/SystemPromptInputProcessorTest.php

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
use Symfony\AI\Platform\Result\ToolCall;
3030
use Symfony\AI\Platform\Tool\ExecutionReference;
3131
use Symfony\AI\Platform\Tool\Tool;
32+
use Symfony\Component\Translation\TranslatableMessage;
3233
use Symfony\Contracts\Translation\TranslatorInterface;
3334

3435
#[CoversClass(SystemPromptInputProcessor::class)]
@@ -106,7 +107,7 @@ public function execute(ToolCall $toolCall): mixed
106107
public function testIncludeToolDefinitions()
107108
{
108109
$processor = new SystemPromptInputProcessor(
109-
'This is a',
110+
new TranslatableMessage('This is a'),
110111
new class implements ToolboxInterface {
111112
public function getTools(): array
112113
{
@@ -130,7 +131,6 @@ public function execute(ToolCall $toolCall): mixed
130131
}
131132
},
132133
$this->getTranslator(),
133-
true,
134134
);
135135

136136
$input = new Input(new Gpt(), new MessageBag(Message::ofUser('This is a user message')));
@@ -196,7 +196,7 @@ public function execute(ToolCall $toolCall): mixed
196196

197197
public function testWithTranslatedSystemPrompt()
198198
{
199-
$processor = new SystemPromptInputProcessor('This is a', null, $this->getTranslator(), true);
199+
$processor = new SystemPromptInputProcessor(new TranslatableMessage('This is a'), null, $this->getTranslator());
200200

201201
$input = new Input(new Gpt(), new MessageBag(Message::ofUser('This is a user message')), []);
202202
$processor->processInput($input);
@@ -211,11 +211,9 @@ public function testWithTranslatedSystemPrompt()
211211
public function testWithTranslationDomainSystemPrompt()
212212
{
213213
$processor = new SystemPromptInputProcessor(
214-
'This is a',
214+
new TranslatableMessage('This is a', domain: 'prompts'),
215215
null,
216216
$this->getTranslator(),
217-
true,
218-
'prompts'
219217
);
220218

221219
$input = new Input(new Gpt(), new MessageBag(), []);
@@ -229,13 +227,12 @@ public function testWithTranslationDomainSystemPrompt()
229227

230228
public function testWithMissingTranslator()
231229
{
232-
$this->expectExceptionMessage('Prompt translation is enabled but no translator was provided');
230+
$this->expectExceptionMessage('Translatable system prompt is not supported when no translator is provided.');
233231

234232
new SystemPromptInputProcessor(
235-
'This is a',
233+
new TranslatableMessage('This is a'),
236234
null,
237235
null,
238-
true,
239236
);
240237
}
241238

src/ai-bundle/composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929
"phpstan/phpstan": "^2.1",
3030
"phpunit/phpunit": "^11.5",
3131
"symfony/expression-language": "^7.3|^8.0",
32-
"symfony/security-core": "^7.3|^8.0"
32+
"symfony/security-core": "^7.3|^8.0",
33+
"symfony/translation": "^7.3|^8.0"
3334
},
3435
"autoload": {
3536
"psr-4": {

src/ai-bundle/src/AiBundle.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
use Symfony\Component\HttpClient\HttpClient;
8585
use Symfony\Component\HttpKernel\Bundle\AbstractBundle;
8686
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
87+
use Symfony\Component\Translation\TranslatableMessage;
8788
use Symfony\Contracts\HttpClient\HttpClientInterface;
8889

8990
use function Symfony\Component\String\u;
@@ -623,13 +624,21 @@ private function processAgentConfig(string $name, array $config, ContainerBuilde
623624
if (isset($config['prompt'])) {
624625
$includeTools = isset($config['prompt']['include_tools']) && $config['prompt']['include_tools'];
625626

627+
if ($config['prompt']['enable_translation']) {
628+
if (!class_exists(TranslatableMessage::class)) {
629+
throw new RuntimeException('For using prompt translataion, symfony/translation package is required. Try running "composer require symfony/translation".');
630+
}
631+
632+
$prompt = new TranslatableMessage($config['prompt']['text'], domain: $config['prompt']['translation_domain']);
633+
} else {
634+
$prompt = $config['prompt']['text'];
635+
}
636+
626637
$systemPromptInputProcessorDefinition = (new Definition(SystemPromptInputProcessor::class))
627638
->setArguments([
628-
$config['prompt']['text'],
639+
$prompt,
629640
$includeTools ? new Reference('ai.toolbox.'.$name) : null,
630641
new Reference('translator', ContainerInterface::NULL_ON_INVALID_REFERENCE),
631-
$config['prompt']['enable_translation'],
632-
$config['prompt']['translation_domain'],
633642
new Reference('logger', ContainerInterface::IGNORE_ON_INVALID_REFERENCE),
634643
])
635644
->addTag('ai.agent.input_processor', ['agent' => $agentId, 'priority' => -30]);

src/ai-bundle/tests/DependencyInjection/AiBundleTest.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
use Symfony\Component\DependencyInjection\ContainerInterface;
3535
use Symfony\Component\DependencyInjection\Definition;
3636
use Symfony\Component\DependencyInjection\Reference;
37+
use Symfony\Component\Translation\TranslatableMessage;
3738

3839
#[CoversClass(AiBundle::class)]
3940
#[UsesClass(ContainerBuilder::class)]
@@ -682,10 +683,8 @@ public function testSystemPromptWithArrayStructure()
682683
$definition = $container->getDefinition('ai.agent.test_agent.system_prompt_processor');
683684
$arguments = $definition->getArguments();
684685

685-
$this->assertSame('You are a helpful assistant.', $arguments[0]);
686+
$this->assertEquals(new TranslatableMessage('You are a helpful assistant.', domain: 'prompts'), $arguments[0]);
686687
$this->assertNull($arguments[1]); // include_tools is false, so null reference
687-
$this->assertTrue($arguments[3]);
688-
$this->assertSame('prompts', $arguments[4]);
689688
}
690689

691690
#[TestDox('System prompt with include_tools enabled works correctly')]

0 commit comments

Comments
 (0)