Skip to content

Commit db970e5

Browse files
committed
ref
1 parent 1ff951c commit db970e5

15 files changed

+195
-92
lines changed

examples/misc/persistent-chat-double-agent.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@
3030
$firstChat = new Chat($firstAgent, $store, '_first_chat');
3131
$secondChat = new Chat($secondAgent, $store, '_second_chat');
3232

33-
$firstChat->setup(new MessageBag(
33+
$firstChat->initiate(new MessageBag(
3434
Message::forSystem('You are a helpful assistant. You only answer with short sentences.'),
3535
));
36-
$secondChat->setup(new MessageBag(
36+
$secondChat->initiate(new MessageBag(
3737
Message::forSystem('You are a helpful assistant. You only answer with short sentences.'),
3838
));
3939

examples/misc/persistent-chat.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
Message::forSystem('You are a helpful assistant. You only answer with short sentences.'),
3030
);
3131

32-
$chat->setup($messages);
32+
$chat->initiate($messages);
3333
$chat->submit(Message::ofUser('My name is Christopher.'));
3434
$message = $chat->submit(Message::ofUser('What is my name?'));
3535

src/agent/src/Chat.php

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,28 +17,33 @@
1717
use Symfony\AI\Platform\Message\MessageBagInterface;
1818
use Symfony\AI\Platform\Message\UserMessage;
1919
use Symfony\AI\Platform\Result\TextResult;
20+
use Symfony\Component\Uid\Uuid;
2021

2122
/**
2223
* @author Christopher Hertel <[email protected]>
2324
*/
24-
final readonly class Chat implements ChatInterface
25+
final class Chat implements ChatInterface
2526
{
27+
private string $bagIdentifier;
28+
2629
public function __construct(
27-
private AgentInterface $agent,
28-
private MessageStoreInterface $store,
29-
private string $storageKey = '_messages',
30+
private readonly AgentInterface $agent,
31+
private readonly MessageStoreInterface $store,
3032
) {
33+
$this->bagIdentifier = Uuid::v7()->toRfc4122();
3134
}
3235

33-
public function setup(MessageBagInterface $messages): void
36+
public function initiate(MessageBagInterface $messages, ?string $bagIdentifier = null): void
3437
{
38+
$this->bagIdentifier = $bagIdentifier ?? $this->bagIdentifier;
39+
3540
$this->store->clear();
36-
$this->store->save($this->storageKey, $messages);
41+
$this->store->save($messages, $this->bagIdentifier);
3742
}
3843

3944
public function submit(UserMessage $message): AssistantMessage
4045
{
41-
$messagesBag = $this->store->load($this->storageKey);
46+
$messagesBag = $this->store->load($this->bagIdentifier);
4247

4348
$messagesBag->add($message);
4449
$result = $this->agent->call($messagesBag);
@@ -48,8 +53,13 @@ public function submit(UserMessage $message): AssistantMessage
4853
$assistantMessage = Message::ofAssistant($result->getContent());
4954
$messagesBag->add($assistantMessage);
5055

51-
$this->store->save($this->storageKey, $messagesBag);
56+
$this->store->save($messagesBag, $this->bagIdentifier);
5257

5358
return $assistantMessage;
5459
}
60+
61+
public function getBagIdentifier(): string
62+
{
63+
return $this->bagIdentifier;
64+
}
5565
}

src/agent/src/Chat/MessageStore/CacheStore.php

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,36 +17,41 @@
1717
use Symfony\AI\Platform\Message\MessageBag;
1818
use Symfony\AI\Platform\Message\MessageBagInterface;
1919

20+
/**
21+
* @author Christopher Hertel <[email protected]>
22+
* @author Oskar Stark <[email protected]>
23+
*/
2024
final readonly class CacheStore implements MessageStoreInterface
2125
{
2226
public function __construct(
2327
private CacheItemPoolInterface $cache,
28+
private string $bagIdentifier = '_cache',
2429
private int $ttl = 86400,
2530
) {
2631
if (!interface_exists(CacheItemPoolInterface::class)) {
2732
throw new RuntimeException('For using the CacheStore as message store, a PSR-6 cache implementation is required. Try running "composer require symfony/cache" or another PSR-6 compatible cache.');
2833
}
2934
}
3035

31-
public function save(string $storageKey, MessageBagInterface $messages): void
36+
public function save(MessageBagInterface $messages, ?string $bagIdentifier = null): void
3237
{
33-
$item = $this->cache->getItem($storageKey);
38+
$item = $this->cache->getItem($bagIdentifier ?? $this->bagIdentifier);
3439

3540
$item->set($messages);
3641
$item->expiresAfter($this->ttl);
3742

3843
$this->cache->save($item);
3944
}
4045

41-
public function load(string $storageKey): MessageBagInterface
46+
public function load(?string $bagIdentifier = null): MessageBagInterface
4247
{
43-
$item = $this->cache->getItem($storageKey);
48+
$item = $this->cache->getItem($bagIdentifier ?? $this->bagIdentifier);
4449

4550
return $item->isHit() ? $item->get() : new MessageBag();
4651
}
4752

48-
public function clear(): void
53+
public function clear(?string $bagIdentifier = null): void
4954
{
50-
$this->cache->clear();
55+
$this->cache->deleteItem($bagIdentifier ?? $this->bagIdentifier);
5156
}
5257
}

src/agent/src/Chat/MessageStore/InMemoryStore.php

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,33 @@
1515
use Symfony\AI\Platform\Message\MessageBag;
1616
use Symfony\AI\Platform\Message\MessageBagInterface;
1717

18+
/**
19+
* @author Christopher Hertel <[email protected]>
20+
*/
1821
final class InMemoryStore implements MessageStoreInterface
1922
{
2023
/**
2124
* @var MessageBagInterface[]
2225
*/
2326
private array $messageBags;
2427

25-
public function save(MessageBagInterface $messages, ?string $key = null): void
28+
public function __construct(
29+
private readonly string $bagIdentifier = '_memory',
30+
) {
31+
}
32+
33+
public function save(MessageBagInterface $messages, ?string $bagIdentifier = null): void
2634
{
27-
$this->messageBags[$key ?? $this->key] = $messages;
35+
$this->messageBags[$bagIdentifier ?? $this->bagIdentifier] = $messages;
2836
}
2937

30-
public function load(string $storageKey): MessageBagInterface
38+
public function load(?string $bagIdentifier = null): MessageBagInterface
3139
{
32-
return $this->messageBags[$storageKey] ?? new MessageBag();
40+
return $this->messageBags[$bagIdentifier ?? $this->bagIdentifier] ?? new MessageBag();
3341
}
3442

35-
public function clear(): void
43+
public function clear(?string $bagIdentifier = null): void
3644
{
37-
$this->messageBags = [];
45+
$this->messageBags[$bagIdentifier ?? $this->bagIdentifier] = new MessageBag();
3846
}
3947
}

src/agent/src/Chat/MessageStore/SessionStore.php

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,17 @@
1818
use Symfony\Component\HttpFoundation\RequestStack;
1919
use Symfony\Component\HttpFoundation\Session\SessionInterface;
2020

21+
/**
22+
* @author Christopher Hertel <[email protected]>
23+
* @author Oskar Stark <[email protected]>
24+
*/
2125
final readonly class SessionStore implements MessageStoreInterface
2226
{
2327
private SessionInterface $session;
2428

2529
public function __construct(
2630
RequestStack $requestStack,
31+
private string $bagId = '_session',
2732
) {
2833
if (!class_exists(RequestStack::class)) {
2934
throw new RuntimeException('For using the SessionStore as message store, the symfony/http-foundation package is required. Try running "composer require symfony/http-foundation".');
@@ -32,18 +37,18 @@ public function __construct(
3237
$this->session = $requestStack->getSession();
3338
}
3439

35-
public function save(string $storageKey, MessageBagInterface $messages): void
40+
public function save(MessageBagInterface $messages, ?string $bagIdentifier = null): void
3641
{
37-
$this->session->set($storageKey, $messages);
42+
$this->session->set($bagIdentifier ?? $this->bagId, $messages);
3843
}
3944

40-
public function load(string $storageKey): MessageBagInterface
45+
public function load(?string $bagIdentifier = null): MessageBagInterface
4146
{
42-
return $this->session->get($storageKey, new MessageBag());
47+
return $this->session->get($bagIdentifier ?? $this->bagId, new MessageBag());
4348
}
4449

45-
public function clear(): void
50+
public function clear(?string $bagIdentifier = null): void
4651
{
47-
$this->session->clear();
52+
$this->session->remove($bagIdentifier ?? $this->bagId);
4853
}
4954
}

src/agent/src/Chat/MessageStoreInterface.php

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,14 @@
1313

1414
use Symfony\AI\Platform\Message\MessageBagInterface;
1515

16+
/**
17+
* @author Christopher Hertel <[email protected]>
18+
*/
1619
interface MessageStoreInterface
1720
{
18-
public function save(MessageBagInterface $messages, ?string $key = null): void;
19-
20-
public function load(?string $key = null): MessageBagInterface;
21+
public function save(MessageBagInterface $messages, ?string $bagIdentifier = null): void;
2122

22-
public function clear(?string $key = null): void;
23+
public function load(?string $bagIdentifier = null): MessageBagInterface;
2324

24-
public function setKey(string $key): void;
25+
public function clear(?string $bagIdentifier = null): void;
2526
}

src/agent/src/ChatInterface.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,18 @@
1616
use Symfony\AI\Platform\Message\MessageBagInterface;
1717
use Symfony\AI\Platform\Message\UserMessage;
1818

19+
/**
20+
* @author Christopher Hertel <[email protected]>
21+
* @author Oskar Stark <[email protected]>
22+
*/
1923
interface ChatInterface
2024
{
21-
public function setup(MessageBagInterface $messages): void;
25+
public function initiate(MessageBagInterface $messages, ?string $bagIdentifier = null): void;
2226

2327
/**
2428
* @throws ExceptionInterface When the chat submission fails due to agent errors
2529
*/
2630
public function submit(UserMessage $message): AssistantMessage;
31+
32+
public function getBagIdentifier(): string;
2733
}

src/agent/tests/AgentTest.php

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
use Symfony\AI\Platform\Result\RawResultInterface;
4141
use Symfony\AI\Platform\Result\ResultInterface;
4242
use Symfony\AI\Platform\Result\ResultPromise;
43+
use Symfony\AI\Platform\Result\TextResult;
4344
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
4445
use Symfony\Contracts\HttpClient\Exception\HttpExceptionInterface;
4546
use Symfony\Contracts\HttpClient\ResponseInterface as HttpResponseInterface;
@@ -404,28 +405,31 @@ public function testConstructorAcceptsTraversableProcessors()
404405
public function testDoubleAgentCanUseSameMessageStore()
405406
{
406407
$platform = $this->createMock(PlatformInterface::class);
408+
$platform->method('invoke')
409+
->willReturn(new ResultPromise(static fn () => new TextResult('Assistant response'), $this->createStub(RawResultInterface::class)));
410+
407411
$model = $this->createMock(Model::class);
408412

409413
$firstAgent = new Agent($platform, $model);
410414
$secondAgent = new Agent($platform, $model);
411415

412416
$store = new InMemoryStore();
413417

414-
$firstChat = new Chat($firstAgent, $store);
415-
$secondChat = new Chat($secondAgent, $store);
418+
$firstChat = new Chat($firstAgent, $store, 'foo');
419+
$secondChat = new Chat($secondAgent, $store, 'bar');
416420

417421
$messages = new MessageBag(
418422
Message::forSystem('You are a helpful assistant. You only answer with short sentences.'),
419423
);
420424

421-
$firstChat->setup($messages);
425+
$firstChat->initiate($messages);
422426
$firstChat->submit(new UserMessage(new Text('Hello')));
423427

424-
$secondChat->setup($messages);
428+
$secondChat->initiate($messages);
425429
$secondChat->submit(new UserMessage(new Text('Hello')));
426430
$secondChat->submit(new UserMessage(new Text('Hello there')));
427431

428-
$this->assertCount(1, $store->load($firstAgent->getId()));
429-
$this->assertCount(2, $store->load($secondAgent->getId()));
432+
$this->assertCount(1, $store->load('foo'));
433+
$this->assertCount(2, $store->load('bar'));
430434
}
431435
}

src/agent/tests/Chat/CacheStoreTest.php

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ public function testItCanStore()
3030
$messageBag->add(Message::ofUser('Hello'));
3131

3232
$store = new CacheStore(new ArrayAdapter());
33-
$store->save('foo', $messageBag);
33+
$store->save($messageBag);
3434

35-
$this->assertCount(1, $store->load($messageBag->getId()));
35+
$this->assertCount(1, $store->load('_cache'));
3636
}
3737

3838
public function testItCanStoreMultipleMessageBags()
@@ -41,32 +41,31 @@ public function testItCanStoreMultipleMessageBags()
4141
$firstMessageBag->add(Message::ofUser('Hello'));
4242

4343
$secondMessageBag = new MessageBag();
44+
$secondMessageBag->add(Message::ofUser('Hello'));
45+
$secondMessageBag->add(Message::ofUser('Hello'));
4446

4547
$store = new CacheStore(new ArrayAdapter());
46-
$store->save('foo', $firstMessageBag);
47-
$store->save('foo', $secondMessageBag);
48+
$store->save($firstMessageBag, 'foo');
49+
$store->save($secondMessageBag, 'bar');
4850

49-
$this->assertCount(1, $store->load($firstMessageBag->getId()));
50-
$this->assertCount(0, $store->load($secondMessageBag->getId()));
51+
$this->assertCount(1, $store->load('foo'));
52+
$this->assertCount(2, $store->load('bar'));
53+
$this->assertCount(0, $store->load('_cache'));
5154
}
5255

5356
public function testItCanClear()
5457
{
55-
$firstMessageBag = new MessageBag();
56-
$firstMessageBag->add(Message::ofUser('Hello'));
57-
58-
$secondMessageBag = new MessageBag();
58+
$bag = new MessageBag();
59+
$bag->add(Message::ofUser('Hello'));
60+
$bag->add(Message::ofUser('Hello'));
5961

6062
$store = new CacheStore(new ArrayAdapter());
61-
$store->save('foo', $firstMessageBag);
62-
$store->save('foo', $secondMessageBag);
63+
$store->save($bag);
6364

64-
$this->assertCount(1, $store->load($firstMessageBag->getId()));
65-
$this->assertCount(0, $store->load($secondMessageBag->getId()));
65+
$this->assertCount(2, $store->load('_cache'));
6666

6767
$store->clear();
6868

69-
$this->assertCount(0, $store->load($firstMessageBag->getId()));
70-
$this->assertCount(0, $store->load($secondMessageBag->getId()));
69+
$this->assertCount(0, $store->load('_cache'));
7170
}
7271
}

0 commit comments

Comments
 (0)