Skip to content

Commit bbf483c

Browse files
Guikingonechr-hertel
authored andcommitted
feat(platform): meilisearch message bag
1 parent e1b2459 commit bbf483c

File tree

14 files changed

+682
-0
lines changed

14 files changed

+682
-0
lines changed

docs/components/chat.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,20 @@ with a ``Symfony\AI\Agent\AgentInterface`` and a ``Symfony\AI\Chat\MessageStoreI
3131

3232
$chat->submit(Message::ofUser('Hello'));
3333

34+
You can find more advanced usage in combination with an Agent using the store for long-term context:
35+
36+
* `External services storage with Cache`_
37+
* `Current session context storage with HttpFoundation session`_
38+
* `Current process context storage with InMemory`_
39+
* `Long-term context with Meilisearch`_
40+
41+
Supported Message stores
42+
------------------------
43+
44+
* `Cache`_
45+
* `HttpFoundation session`_
46+
* `InMemory`_
47+
* `Meilisearch`_
3448

3549
Implementing a Bridge
3650
---------------------
@@ -105,3 +119,12 @@ store and ``bin/console ai:message-store:drop`` to clean up the message store:
105119
106120
$ php bin/console ai:message-store:setup symfonycon
107121
$ php bin/console ai:message-store:drop symfonycon
122+
123+
.. _`External services storage with Cache`: https://github.com/symfony/ai/blob/main/examples/chat/persistent-chat-cache.php
124+
.. _`Current session context storage with HttpFoundation session`: https://github.com/symfony/ai/blob/main/examples/chat/persistent-chat-session.php
125+
.. _`Current process context storage with InMemory`: https://github.com/symfony/ai/blob/main/examples/chat/persistent-chat.php
126+
.. _`Long-term context with Meilisearch`: https://github.com/symfony/ai/blob/main/examples/chat/persistent-chat-meilisearch.php
127+
.. _`Cache`: https://symfony.com/doc/current/components/cache.html
128+
.. _`InMemory`: https://www.php.net/manual/en/language.types.array.php
129+
.. _`HttpFoundation session`: https://developers.cloudflare.com/vectorize/
130+
.. _`Meilisearch`: https://www.meilisearch.com/
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
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\Chat\Bridge\Meilisearch\MessageStore;
14+
use Symfony\AI\Chat\Chat;
15+
use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory;
16+
use Symfony\AI\Platform\Message\Message;
17+
use Symfony\AI\Platform\Message\MessageBag;
18+
use Symfony\Component\Clock\MonotonicClock;
19+
20+
require_once dirname(__DIR__).'/bootstrap.php';
21+
22+
$platform = PlatformFactory::create(env('OPENAI_API_KEY'), http_client());
23+
24+
$store = new MessageStore(http_client(), env('MEILISEARCH_HOST'), env('MEILISEARCH_API_KEY'), new MonotonicClock());
25+
$store->setup();
26+
27+
$agent = new Agent($platform, 'gpt-4o-mini');
28+
$chat = new Chat($agent, $store);
29+
30+
$messages = new MessageBag(
31+
Message::forSystem('You are a helpful assistant. You only answer with short sentences.'),
32+
);
33+
34+
$chat->initiate($messages);
35+
$chat->submit(Message::ofUser('My name is Christopher.'));
36+
$message = $chat->submit(Message::ofUser('What is my name?'));
37+
38+
echo $message->getContent().\PHP_EOL;

examples/commands/message-stores.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414
use Symfony\AI\Chat\Bridge\HttpFoundation\SessionStore;
1515
use Symfony\AI\Chat\Bridge\Local\CacheStore;
1616
use Symfony\AI\Chat\Bridge\Local\InMemoryStore;
17+
use Symfony\AI\Chat\Bridge\Meilisearch\MessageStore as MeilisearchMessageStore;
1718
use Symfony\AI\Chat\Command\DropStoreCommand;
1819
use Symfony\AI\Chat\Command\SetupStoreCommand;
1920
use Symfony\Component\Cache\Adapter\ArrayAdapter;
21+
use Symfony\Component\Clock\MonotonicClock;
2022
use Symfony\Component\Console\Application;
2123
use Symfony\Component\Console\Input\ArrayInput;
2224
use Symfony\Component\Console\Output\ConsoleOutput;
@@ -28,6 +30,13 @@
2830

2931
$factories = [
3032
'cache' => static fn (): CacheStore => new CacheStore(new ArrayAdapter(), cacheKey: 'symfony'),
33+
'meilisearch' => static fn (): MeilisearchMessageStore => new MeilisearchMessageStore(
34+
http_client(),
35+
env('MEILISEARCH_HOST'),
36+
env('MEILISEARCH_API_KEY'),
37+
new MonotonicClock(),
38+
'symfony',
39+
),
3140
'memory' => static fn (): InMemoryStore => new InMemoryStore('symfony'),
3241
'session' => static function (): SessionStore {
3342
$request = Request::create('/');

examples/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"symfony/ai-platform": "@dev",
2222
"symfony/ai-store": "@dev",
2323
"symfony/cache": "^7.3|^8.0",
24+
"symfony/clock": "^7.3|^8.0",
2425
"symfony/console": "^7.3|^8.0",
2526
"symfony/css-selector": "^7.3|^8.0",
2627
"symfony/dependency-injection": "^7.3|^8.0",

src/ai-bundle/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"phpstan/phpstan": "^2.1",
3131
"phpstan/phpstan-strict-rules": "^2.0",
3232
"phpunit/phpunit": "^11.5",
33+
"symfony/clock": "^7.3|^8.0",
3334
"symfony/expression-language": "^7.3|^8.0",
3435
"symfony/security-core": "^7.3|^8.0",
3536
"symfony/translation": "^7.3|^8.0"

src/ai-bundle/config/options.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,16 @@
745745
->end()
746746
->end()
747747
->end()
748+
->arrayNode('meilisearch')
749+
->useAttributeAsKey('name')
750+
->arrayPrototype()
751+
->children()
752+
->stringNode('endpoint')->cannotBeEmpty()->end()
753+
->stringNode('api_key')->cannotBeEmpty()->end()
754+
->stringNode('index_name')->cannotBeEmpty()->end()
755+
->end()
756+
->end()
757+
->end()
748758
->arrayNode('session')
749759
->useAttributeAsKey('name')
750760
->arrayPrototype()

src/ai-bundle/src/AiBundle.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
use Symfony\AI\AiBundle\Profiler\TraceableToolbox;
3636
use Symfony\AI\AiBundle\Security\Attribute\IsGrantedTool;
3737
use Symfony\AI\Chat\Bridge\HttpFoundation\SessionStore;
38+
use Symfony\AI\Chat\Bridge\Meilisearch\MessageStore as MeilisearchMessageStore;
3839
use Symfony\AI\Chat\MessageStoreInterface;
3940
use Symfony\AI\Platform\Bridge\Anthropic\PlatformFactory as AnthropicPlatformFactory;
4041
use Symfony\AI\Platform\Bridge\Azure\OpenAi\PlatformFactory as AzureOpenAiPlatformFactory;
@@ -82,6 +83,7 @@
8283
use Symfony\AI\Store\Indexer;
8384
use Symfony\AI\Store\IndexerInterface;
8485
use Symfony\AI\Store\StoreInterface;
86+
use Symfony\Component\Clock\ClockInterface;
8587
use Symfony\Component\Config\Definition\Configurator\DefinitionConfigurator;
8688
use Symfony\Component\DependencyInjection\Attribute\Target;
8789
use Symfony\Component\DependencyInjection\ChildDefinition;
@@ -1331,6 +1333,24 @@ private function processMessageStoreConfig(string $type, array $messageStores, C
13311333
}
13321334
}
13331335

1336+
if ('meilisearch' === $type) {
1337+
foreach ($messageStores as $name => $messageStore) {
1338+
$definition = new Definition(MeilisearchMessageStore::class);
1339+
$definition
1340+
->setArguments([
1341+
$messageStore['endpoint'],
1342+
$messageStore['api_key'],
1343+
new Reference(ClockInterface::class),
1344+
$messageStore['index_name'],
1345+
])
1346+
->addTag('ai.message_store');
1347+
1348+
$container->setDefinition('ai.message_store.'.$type.'.'.$name, $definition);
1349+
$container->registerAliasForArgument('ai.message_store.'.$type.'.'.$name, MessageStoreInterface::class, $name);
1350+
$container->registerAliasForArgument('ai.message_store.'.$type.'.'.$name, MessageStoreInterface::class, $type.'_'.$name);
1351+
}
1352+
}
1353+
13341354
if ('session' === $type) {
13351355
foreach ($messageStores as $name => $messageStore) {
13361356
$definition = new Definition(SessionStore::class);

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3035,6 +3035,13 @@ private function getFullConfig(): array
30353035
'identifier' => '_memory',
30363036
],
30373037
],
3038+
'meilisearch' => [
3039+
'my_meilisearch_store' => [
3040+
'endpoint' => 'http://127.0.0.1:7700',
3041+
'api_key' => 'foo',
3042+
'index_name' => 'test',
3043+
],
3044+
],
30383045
'session' => [
30393046
'my_session_message_store' => [
30403047
'identifier' => 'session',

src/chat/composer.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,14 @@
2929
"phpstan/phpstan-strict-rules": "^2.0",
3030
"phpunit/phpunit": "^11.5.13",
3131
"symfony/dependency-injection": "^7.3|^8.0",
32+
"symfony/clock": "^7.3|^8.0",
3233
"symfony/console": "^7.3|^8.0",
3334
"symfony/http-foundation": "^7.3|^8.0",
3435
"psr/cache": "^3.0"
3536
},
37+
"suggest": {
38+
"symfony/clock": "To use stores that requires waiting for actions like Meilisearch"
39+
},
3640
"autoload": {
3741
"psr-4": {
3842
"Symfony\\AI\\Chat\\": "src/"

0 commit comments

Comments
 (0)