Skip to content

Commit a9420af

Browse files
committed
feature #889 [Chat] Add Pogocache store serializer usage (Guikingone)
This PR was merged into the main branch. Discussion ---------- [Chat] Add `Pogocache` store serializer usage | Q | A | ------------- | --- | Bug fix? | no | New feature? | no | Docs? | yes | Issues | #16 | License | MIT Commits ------- cf43927 refactor(chat): Pogocache store serializer usage
2 parents ad0206a + cf43927 commit a9420af

File tree

4 files changed

+36
-110
lines changed

4 files changed

+36
-110
lines changed

src/ai-bundle/src/AiBundle.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1540,6 +1540,7 @@ private function processMessageStoreConfig(string $type, array $messageStores, C
15401540
$messageStore['endpoint'],
15411541
$messageStore['password'],
15421542
$messageStore['key'],
1543+
new Reference('serializer'),
15431544
])
15441545
->addTag('proxy', ['interface' => MessageStoreInterface::class])
15451546
->addTag('ai.message_store');

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2924,11 +2924,14 @@ public function testPogocacheMessageStoreIsConfigured()
29242924
$pogocacheMessageStoreDefinition = $container->getDefinition('ai.message_store.pogocache.custom');
29252925

29262926
$this->assertTrue($pogocacheMessageStoreDefinition->isLazy());
2927+
$this->assertCount(5, $pogocacheMessageStoreDefinition->getArguments());
29272928
$this->assertInstanceOf(Reference::class, $pogocacheMessageStoreDefinition->getArgument(0));
29282929
$this->assertSame('http_client', (string) $pogocacheMessageStoreDefinition->getArgument(0));
29292930
$this->assertSame('http://127.0.0.1:9401', $pogocacheMessageStoreDefinition->getArgument(1));
29302931
$this->assertSame('foo', $pogocacheMessageStoreDefinition->getArgument(2));
29312932
$this->assertSame('bar', $pogocacheMessageStoreDefinition->getArgument(3));
2933+
$this->assertInstanceOf(Reference::class, $pogocacheMessageStoreDefinition->getArgument(4));
2934+
$this->assertSame('serializer', (string) $pogocacheMessageStoreDefinition->getArgument(4));
29322935

29332936
$this->assertTrue($pogocacheMessageStoreDefinition->hasTag('proxy'));
29342937
$this->assertSame([['interface' => MessageStoreInterface::class]], $pogocacheMessageStoreDefinition->getTag('proxy'));

src/chat/src/Bridge/Pogocache/MessageStore.php

Lines changed: 14 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,17 @@
1212
namespace Symfony\AI\Chat\Bridge\Pogocache;
1313

1414
use Symfony\AI\Chat\Exception\InvalidArgumentException;
15-
use Symfony\AI\Chat\Exception\LogicException;
1615
use Symfony\AI\Chat\ManagedStoreInterface;
16+
use Symfony\AI\Chat\MessageNormalizer;
1717
use Symfony\AI\Chat\MessageStoreInterface;
18-
use Symfony\AI\Platform\Message\AssistantMessage;
19-
use Symfony\AI\Platform\Message\Content\Audio;
20-
use Symfony\AI\Platform\Message\Content\ContentInterface;
21-
use Symfony\AI\Platform\Message\Content\DocumentUrl;
22-
use Symfony\AI\Platform\Message\Content\File;
23-
use Symfony\AI\Platform\Message\Content\Image;
24-
use Symfony\AI\Platform\Message\Content\ImageUrl;
25-
use Symfony\AI\Platform\Message\Content\Text;
2618
use Symfony\AI\Platform\Message\MessageBag;
2719
use Symfony\AI\Platform\Message\MessageInterface;
28-
use Symfony\AI\Platform\Message\SystemMessage;
29-
use Symfony\AI\Platform\Message\ToolCallMessage;
30-
use Symfony\AI\Platform\Message\UserMessage;
31-
use Symfony\AI\Platform\Result\ToolCall;
20+
use Symfony\Component\Serializer\Encoder\JsonEncoder;
21+
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
22+
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
23+
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
24+
use Symfony\Component\Serializer\Serializer;
25+
use Symfony\Component\Serializer\SerializerInterface;
3226
use Symfony\Contracts\HttpClient\HttpClientInterface;
3327

3428
/**
@@ -41,6 +35,10 @@ public function __construct(
4135
private readonly string $host,
4236
#[\SensitiveParameter] private readonly string $password,
4337
private readonly string $key = '_message_store_pogocache',
38+
private readonly SerializerInterface&NormalizerInterface&DenormalizerInterface $serializer = new Serializer([
39+
new ArrayDenormalizer(),
40+
new MessageNormalizer(),
41+
], [new JsonEncoder()]),
4442
) {
4543
}
4644

@@ -60,11 +58,9 @@ public function drop(): void
6058

6159
public function save(MessageBag $messages): void
6260
{
63-
$messages = $messages->getMessages();
64-
6561
$this->request('PUT', $this->key, array_map(
66-
$this->convertToIndexableArray(...),
67-
$messages,
62+
fn (MessageInterface $message): array => $this->serializer->normalize($message),
63+
$messages->getMessages(),
6864
));
6965
}
7066

@@ -73,7 +69,7 @@ public function load(): MessageBag
7369
$messages = $this->request('GET', $this->key);
7470

7571
return new MessageBag(...array_map(
76-
$this->convertToMessage(...),
72+
fn (array $message): MessageInterface => $this->serializer->denormalize($message, MessageInterface::class),
7773
$messages,
7874
));
7975
}
@@ -97,87 +93,4 @@ private function request(string $method, string $endpoint, array $payload = []):
9793

9894
return [];
9995
}
100-
101-
/**
102-
* @return array<string, mixed>
103-
*/
104-
private function convertToIndexableArray(MessageInterface $message): array
105-
{
106-
$toolsCalls = [];
107-
108-
if ($message instanceof AssistantMessage && $message->hasToolCalls()) {
109-
$toolsCalls = array_map(
110-
static fn (ToolCall $toolCall): array => $toolCall->jsonSerialize(),
111-
$message->getToolCalls(),
112-
);
113-
}
114-
115-
if ($message instanceof ToolCallMessage) {
116-
$toolsCalls = $message->getToolCall()->jsonSerialize();
117-
}
118-
119-
return [
120-
'id' => $message->getId()->toRfc4122(),
121-
'type' => $message::class,
122-
'content' => ($message instanceof SystemMessage || $message instanceof AssistantMessage || $message instanceof ToolCallMessage) ? $message->getContent() : '',
123-
'contentAsBase64' => ($message instanceof UserMessage && [] !== $message->getContent()) ? array_map(
124-
static fn (ContentInterface $content) => [
125-
'type' => $content::class,
126-
'content' => match ($content::class) {
127-
Text::class => $content->getText(),
128-
File::class,
129-
Image::class,
130-
Audio::class => $content->asBase64(),
131-
ImageUrl::class,
132-
DocumentUrl::class => $content->getUrl(),
133-
default => throw new LogicException(\sprintf('Unknown content type "%s".', $content::class)),
134-
},
135-
],
136-
$message->getContent(),
137-
) : [],
138-
'toolsCalls' => $toolsCalls,
139-
'metadata' => $message->getMetadata()->all(),
140-
];
141-
}
142-
143-
/**
144-
* @param array<string, mixed> $payload
145-
*/
146-
private function convertToMessage(array $payload): MessageInterface
147-
{
148-
$type = $payload['type'];
149-
$content = $payload['content'] ?? '';
150-
$contentAsBase64 = $payload['contentAsBase64'] ?? [];
151-
152-
$message = match ($type) {
153-
SystemMessage::class => new SystemMessage($content),
154-
AssistantMessage::class => new AssistantMessage($content, array_map(
155-
static fn (array $toolsCall): ToolCall => new ToolCall(
156-
$toolsCall['id'],
157-
$toolsCall['function']['name'],
158-
json_decode($toolsCall['function']['arguments'], true)
159-
),
160-
$payload['toolsCalls'],
161-
)),
162-
UserMessage::class => new UserMessage(...array_map(
163-
static fn (array $contentAsBase64): ContentInterface => \in_array($contentAsBase64['type'], [File::class, Image::class, Audio::class], true)
164-
? $contentAsBase64['type']::fromDataUrl($contentAsBase64['content'])
165-
: new $contentAsBase64['type']($contentAsBase64['content']),
166-
$contentAsBase64,
167-
)),
168-
ToolCallMessage::class => new ToolCallMessage(
169-
new ToolCall(
170-
$payload['toolsCalls']['id'],
171-
$payload['toolsCalls']['function']['name'],
172-
json_decode($payload['toolsCalls']['function']['arguments'], true)
173-
),
174-
$content
175-
),
176-
default => throw new LogicException(\sprintf('Unknown message type "%s".', $type)),
177-
};
178-
179-
$message->getMetadata()->set($payload['metadata']);
180-
181-
return $message;
182-
}
18396
}

src/chat/tests/Bridge/Pogocache/MessageStoreTest.php

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,20 @@
1111

1212
namespace Symfony\AI\Chat\Tests\Bridge\Pogocache;
1313

14-
use PHPUnit\Framework\Attributes\DataProvider;
14+
use PHPUnit\Framework\TestCase;
1515
use Symfony\AI\Chat\Bridge\Pogocache\MessageStore;
16-
use Symfony\AI\Chat\Tests\MessageStoreTestCase;
16+
use Symfony\AI\Chat\MessageNormalizer;
1717
use Symfony\AI\Platform\Message\Message;
1818
use Symfony\AI\Platform\Message\MessageBag;
19+
use Symfony\AI\Platform\Message\UserMessage;
1920
use Symfony\Component\HttpClient\Exception\ClientException;
2021
use Symfony\Component\HttpClient\MockHttpClient;
2122
use Symfony\Component\HttpClient\Response\JsonMockResponse;
23+
use Symfony\Component\Serializer\Encoder\JsonEncoder;
24+
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
25+
use Symfony\Component\Serializer\Serializer;
2226

23-
final class MessageStoreTest extends MessageStoreTestCase
27+
final class MessageStoreTest extends TestCase
2428
{
2529
public function testStoreCannotSetupOnInvalidResponse()
2630
{
@@ -131,23 +135,28 @@ public function testStoreCannotLoadMessagesOnInvalidResponse()
131135
$store->load();
132136
}
133137

134-
/**
135-
* @param array<mixed, mixed> $payload
136-
*/
137-
#[DataProvider('provideMessages')]
138-
public function testStoreCanLoadMessages(array $payload)
138+
public function testStoreCanLoadMessages()
139139
{
140+
$serializer = new Serializer([
141+
new ArrayDenormalizer(),
142+
new MessageNormalizer(),
143+
], [new JsonEncoder()]);
144+
145+
$payload = $serializer->normalize(Message::ofUser('Hello World'));
146+
140147
$httpClient = new MockHttpClient([
141148
new JsonMockResponse([$payload], [
142149
'http_code' => 200,
143150
]),
144151
], 'http://127.0.0.1:9401');
145152

146-
$store = new MessageStore($httpClient, 'http://127.0.0.1:9401', 'test', 'test');
153+
$store = new MessageStore($httpClient, 'http://127.0.0.1:9401', 'test', 'test', $serializer);
147154

148155
$messageBag = $store->load();
149156

150157
$this->assertCount(1, $messageBag);
151158
$this->assertSame(1, $httpClient->getRequestsCount());
159+
$this->assertInstanceOf(UserMessage::class, $messageBag->getUserMessage());
160+
$this->assertSame('Hello World', $messageBag->getUserMessage()->asText());
152161
}
153162
}

0 commit comments

Comments
 (0)