Skip to content

Commit 331c3cb

Browse files
committed
refactor(platform): fix for CachedPlatform
1 parent 43e8030 commit 331c3cb

28 files changed

+894
-172
lines changed

docs/bundles/ai-bundle.rst

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,6 @@ this platform allows to reduce network calls / resource consumption:
195195
api_key: '%env(OPENAI_API_KEY)%'
196196
cache:
197197
platform: 'ai.platform.openai'
198-
service: 'cache.app'
199198
200199
agent:
201200
openai:

docs/components/platform.rst

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -526,15 +526,17 @@ Cached Platform Calls
526526

527527
Thanks to Symfony's Cache component, platform calls can be cached to reduce calls and resources consumption::
528528

529-
use Symfony\AI\Platform\Bridge\Ollama\PlatformFactory;
530-
use Symfony\AI\Platform\CachedPlatform;
529+
use Symfony\AI\Agent\Agent;
530+
use Symfony\AI\Platform\Bridge\Cache\CachedPlatform;
531+
use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory;
531532
use Symfony\AI\Platform\Message\Message;
532533
use Symfony\AI\Platform\Message\MessageBag;
533534
use Symfony\Component\Cache\Adapter\ArrayAdapter;
534535
use Symfony\Component\Cache\Adapter\TagAwareAdapter;
536+
use Symfony\Component\HttpClient\HttpClient;
535537

536-
$platform = PlatformFactory::create($apiKey, eventDispatcher: $dispatcher);
537-
$cachedPlatform = new CachedPlatform($platform, new TagAwareAdapter(new ArrayAdapter());
538+
$platform = PlatformFactory::create($apiKey, HttpClient::create());
539+
$cachedPlatform = new CachedPlatform($platform, cache: new TagAwareAdapter(new ArrayAdapter()));
538540

539541
$firstResult = $cachedPlatform->invoke('gpt-4o-mini', new MessageBag(Message::ofUser('What is the capital of France?')));
540542

@@ -557,6 +559,7 @@ the :class:`Symfony\\AI\\Platform\\Bridge\\Failover\\FailoverPlatform` can be us
557559
use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory as OpenAiPlatformFactory;
558560
use Symfony\AI\Platform\Message\Message;
559561
use Symfony\AI\Platform\Message\MessageBag;
562+
use Symfony\Component\HttpClient\HttpClient;
560563
use Symfony\Component\RateLimiter\RateLimiterFactory;
561564
use Symfony\Component\RateLimiter\Storage\InMemoryStorage;
562565

@@ -569,8 +572,8 @@ the :class:`Symfony\\AI\\Platform\\Bridge\\Failover\\FailoverPlatform` can be us
569572

570573
// # Ollama will fail as 'gpt-4o' is not available in the catalog
571574
$platform = new FailoverPlatform([
572-
OllamaPlatformFactory::create(env('OLLAMA_HOST_URL'), http_client()),
573-
OpenAiPlatformFactory::create(env('OPENAI_API_KEY'), http_client()),
575+
OllamaPlatformFactory::create(env('OLLAMA_HOST_URL'), HttpClient::create()),
576+
OpenAiPlatformFactory::create(env('OPENAI_API_KEY'), HttpClient::create()),
574577
], $rateLimiter);
575578

576579
$result = $platform->invoke('gpt-4o', new MessageBag(

examples/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"symfony/ai-bedrock-platform": "^0.2",
3333
"symfony/ai-brave-tool": "^0.2",
3434
"symfony/ai-cache-message-store": "^0.2",
35+
"symfony/ai-cache-platform": "^0.2",
3536
"symfony/ai-cache-store": "^0.2",
3637
"symfony/ai-cartesia-platform": "^0.2",
3738
"symfony/ai-cerebras-platform": "^0.2",

examples/misc/agent-with-cache.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,19 @@
1010
*/
1111

1212
use Symfony\AI\Agent\Agent;
13-
use Symfony\AI\Platform\Bridge\Ollama\PlatformFactory;
14-
use Symfony\AI\Platform\CachedPlatform;
13+
use Symfony\AI\Platform\Bridge\Cache\CachePlatform;
14+
use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory;
1515
use Symfony\AI\Platform\Message\Message;
1616
use Symfony\AI\Platform\Message\MessageBag;
1717
use Symfony\Component\Cache\Adapter\ArrayAdapter;
1818
use Symfony\Component\Cache\Adapter\TagAwareAdapter;
1919

2020
require_once dirname(__DIR__).'/bootstrap.php';
2121

22-
$platform = PlatformFactory::create(env('OLLAMA_HOST_URL'), http_client());
23-
$cachedPlatform = new CachedPlatform($platform, cache: new TagAwareAdapter(new ArrayAdapter()));
22+
$platform = PlatformFactory::create(env('OPENAI_API_KEY'), http_client());
23+
$cachedPlatform = new CachePlatform($platform, cache: new TagAwareAdapter(new ArrayAdapter()));
2424

25-
$agent = new Agent($cachedPlatform, 'qwen3:0.6b-q4_K_M');
25+
$agent = new Agent($cachedPlatform, 'gpt-5o-mini');
2626
$messages = new MessageBag(
2727
Message::forSystem('You are a helpful assistant.'),
2828
Message::ofUser('Tina has one brother and one sister. How many sisters do Tina\'s siblings have?'),
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
use Symfony\AI\Agent\Agent;
13+
use Symfony\AI\Platform\Bridge\Cache\CachePlatform;
14+
use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory;
15+
use Symfony\AI\Platform\Message\Message;
16+
use Symfony\AI\Platform\Message\MessageBag;
17+
use Symfony\Component\Cache\Adapter\RedisTagAwareAdapter;
18+
19+
require_once dirname(__DIR__).'/bootstrap.php';
20+
21+
$platform = PlatformFactory::create(env('OPENAI_API_KEY'), http_client());
22+
$cachedPlatform = new CachePlatform($platform, cache: new RedisTagAwareAdapter(new Redis([
23+
'host' => 'localhost',
24+
'port' => 6379,
25+
])));
26+
27+
$agent = new Agent($cachedPlatform, 'gpt-5o-mini');
28+
$messages = new MessageBag(
29+
Message::forSystem('You are a helpful assistant.'),
30+
Message::ofUser('Tina has one brother and one sister. How many sisters do Tina\'s siblings have?'),
31+
);
32+
$result = $agent->call($messages, [
33+
'prompt_cache_key' => 'chat',
34+
]);
35+
36+
assert($result->getMetadata()->has('cached'));
37+
38+
echo $result->getContent().\PHP_EOL;
39+
40+
// Thanks to the cache adapter and the "prompt_cache_key" key, this call will not trigger any network call
41+
42+
$secondResult = $agent->call($messages, [
43+
'prompt_cache_key' => 'chat',
44+
]);
45+
46+
assert($secondResult->getMetadata()->has('cached'));
47+
48+
echo $secondResult->getContent().\PHP_EOL;

splitsh.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
"ai-anthropic-platform": "src/platform/src/Bridge/Anthropic",
4343
"ai-azure-platform": "src/platform/src/Bridge/Azure",
4444
"ai-bedrock-platform": "src/platform/src/Bridge/Bedrock",
45+
"ai-cache-platform": "src/platform/src/Bridge/Cache",
4546
"ai-cartesia-platform": "src/platform/src/Bridge/Cartesia",
4647
"ai-cerebras-platform": "src/platform/src/Bridge/Cerebras",
4748
"ai-decart-platform": "src/platform/src/Bridge/Decart",

src/ai-bundle/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"symfony/ai-azure-search-store": "^0.2",
4242
"symfony/ai-bedrock-platform": "^0.2",
4343
"symfony/ai-cache-message-store": "^0.2",
44+
"symfony/ai-cache-platform": "^0.2",
4445
"symfony/ai-cache-store": "^0.2",
4546
"symfony/ai-cartesia-platform": "^0.2",
4647
"symfony/ai-cerebras-platform": "^0.2",

src/ai-bundle/config/options.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,13 @@
8080
->children()
8181
->stringNode('platform')->isRequired()->end()
8282
->stringNode('service')
83-
->isRequired()
8483
->info('The cache service id as defined under the "cache" configuration key')
84+
->defaultValue('cache.app')
8585
->end()
8686
->stringNode('cache_key')
8787
->info('Key used to store platform results, if not set, the current platform name will be used, the "prompt_cache_key" can be set during platform call to override this value')
8888
->end()
89+
->integerNode('ttl')->end()
8990
->end()
9091
->end()
9192
->end()

src/ai-bundle/config/services.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
use Symfony\AI\Platform\Message\TemplateRenderer\StringTemplateRenderer;
6565
use Symfony\AI\Platform\Message\TemplateRenderer\TemplateRendererRegistry;
6666
use Symfony\AI\Platform\ModelCatalog\ModelCatalogInterface;
67+
use Symfony\AI\Platform\Serializer\ResultNormalizer;
6768
use Symfony\AI\Platform\Serializer\StructuredOutputSerializer;
6869
use Symfony\AI\Platform\StructuredOutput\PlatformSubscriber;
6970
use Symfony\AI\Platform\StructuredOutput\ResponseFormatFactory;
@@ -221,6 +222,12 @@
221222
->set('ai.chat.message_bag.normalizer', MessageNormalizer::class)
222223
->tag('serializer.normalizer')
223224

225+
->set('ai.platform.result_normalizer', ResultNormalizer::class)
226+
->args([
227+
service('serializer.normalizer.object'),
228+
])
229+
->tag('serializer.normalizer')
230+
224231
// commands
225232
->set('ai.command.chat', AgentCallCommand::class)
226233
->args([

src/ai-bundle/src/AiBundle.php

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
use Symfony\AI\Platform\Bridge\Anthropic\PlatformFactory as AnthropicPlatformFactory;
5656
use Symfony\AI\Platform\Bridge\Azure\OpenAi\PlatformFactory as AzureOpenAiPlatformFactory;
5757
use Symfony\AI\Platform\Bridge\Bedrock\PlatformFactory as BedrockFactory;
58+
use Symfony\AI\Platform\Bridge\Cache\CachePlatform;
5859
use Symfony\AI\Platform\Bridge\Cartesia\PlatformFactory as CartesiaPlatformFactory;
5960
use Symfony\AI\Platform\Bridge\Cerebras\PlatformFactory as CerebrasPlatformFactory;
6061
use Symfony\AI\Platform\Bridge\Decart\PlatformFactory as DecartPlatformFactory;
@@ -78,7 +79,6 @@
7879
use Symfony\AI\Platform\Bridge\TransformersPhp\PlatformFactory as TransformersPhpPlatformFactory;
7980
use Symfony\AI\Platform\Bridge\VertexAi\PlatformFactory as VertexAiPlatformFactory;
8081
use Symfony\AI\Platform\Bridge\Voyage\PlatformFactory as VoyagePlatformFactory;
81-
use Symfony\AI\Platform\CachedPlatform;
8282
use Symfony\AI\Platform\Capability;
8383
use Symfony\AI\Platform\Exception\RuntimeException;
8484
use Symfony\AI\Platform\Message\Content\File;
@@ -514,20 +514,26 @@ private function processPlatformConfig(string $type, array $platform, ContainerB
514514
}
515515

516516
if ('cache' === $type) {
517-
foreach ($platform as $name => $cachedPlatformConfig) {
518-
$definition = (new Definition(CachedPlatform::class))
517+
foreach ($platform as $name => $cachePlatformConfig) {
518+
if (!ContainerBuilder::willBeAvailable('symfony/ai-cache-platform', CachePlatform::class, ['symfony/ai-bundle'])) {
519+
throw new RuntimeException('CachePlatform platform configuration requires "symfony/ai-cache-platform" package. Try running "composer require symfony/ai-cache-platform".');
520+
}
521+
522+
$definition = (new Definition(CachePlatform::class))
519523
->setLazy(true)
520524
->setArguments([
521-
new Reference($cachedPlatformConfig['platform']),
525+
new Reference($cachePlatformConfig['platform']),
522526
new Reference(ClockInterface::class),
523-
new Reference($cachedPlatformConfig['service'], ContainerInterface::NULL_ON_INVALID_REFERENCE),
524-
$cachedPlatformConfig['cache_key'] ?? $name,
527+
new Reference($cachePlatformConfig['service'], ContainerInterface::NULL_ON_INVALID_REFERENCE),
528+
new Reference('serializer'),
529+
$cachePlatformConfig['cache_key'] ?? $name,
530+
$cachePlatformConfig['ttl'] ?? null,
525531
])
526532
->addTag('proxy', ['interface' => PlatformInterface::class])
527533
->addTag('ai.platform', ['name' => 'cache.'.$name]);
528534

529-
$container->setDefinition('ai.platform.cache.'.$name, $definition);
530-
$container->registerAliasForArgument('ai.platform.'.$type, PlatformInterface::class, $type.'_'.$name);
535+
$container->setDefinition('ai.platform.'.$type.'.'.$name, $definition);
536+
$container->registerAliasForArgument('ai.platform.'.$type.'.'.$name, PlatformInterface::class, $type.'_'.$name);
531537
}
532538

533539
return;

0 commit comments

Comments
 (0)