|
26 | 26 | use Symfony\AI\Platform\PlatformInterface; |
27 | 27 | use Symfony\AI\Platform\Result\DeferredResult; |
28 | 28 | use Symfony\AI\Platform\Result\InMemoryRawResult; |
| 29 | +use Symfony\AI\Platform\Result\StreamResult as GenericStreamResult; |
29 | 30 | use Symfony\AI\Platform\Result\TextResult; |
30 | 31 | use Symfony\AI\Platform\Result\ToolCall; |
31 | 32 | use Symfony\AI\Platform\Result\ToolCallResult; |
@@ -233,4 +234,52 @@ public function testSourcesGetCollectedAcrossConsecutiveToolCalls() |
233 | 234 | $this->assertCount(2, $metadata->get('sources')); |
234 | 235 | $this->assertSame([$source1, $source2], $metadata->get('sources')); |
235 | 236 | } |
| 237 | + |
| 238 | + public function testSourcesEndUpInResultMetadataWithStreaming() |
| 239 | + { |
| 240 | + $toolCall = new ToolCall('call_1234', 'tool_sources', ['arg1' => 'value1']); |
| 241 | + $source1 = new Source('Relevant Article 1', 'http://example.com/article1', 'Content of article about the topic'); |
| 242 | + $source2 = new Source('Relevant Article 2', 'http://example.com/article2', 'More content of article about the topic'); |
| 243 | + $toolbox = $this->createMock(ToolboxInterface::class); |
| 244 | + $toolbox |
| 245 | + ->expects($this->once()) |
| 246 | + ->method('execute') |
| 247 | + ->willReturn(new ToolResult($toolCall, 'Response based on the two articles.', [$source1, $source2])); |
| 248 | + |
| 249 | + $messageBag = new MessageBag(); |
| 250 | + |
| 251 | + // Create a generator that yields chunks and then a ToolCallResult |
| 252 | + $generator = (function () use ($toolCall) { |
| 253 | + yield 'chunk1'; |
| 254 | + yield 'chunk2'; |
| 255 | + yield new ToolCallResult($toolCall); |
| 256 | + })(); |
| 257 | + |
| 258 | + $result = new GenericStreamResult($generator); |
| 259 | + |
| 260 | + $agent = $this->createMock(AgentInterface::class); |
| 261 | + $agent |
| 262 | + ->expects($this->once()) |
| 263 | + ->method('call') |
| 264 | + ->willReturn(new TextResult('Final response based on the two articles.')); |
| 265 | + |
| 266 | + $processor = new AgentProcessor($toolbox, includeSources: true); |
| 267 | + $processor->setAgent($agent); |
| 268 | + |
| 269 | + $output = new Output('gpt-4', $result, $messageBag); |
| 270 | + |
| 271 | + $processor->processOutput($output); |
| 272 | + |
| 273 | + // Consume the stream |
| 274 | + $content = ''; |
| 275 | + foreach ($output->getResult()->getContent() as $chunk) { |
| 276 | + $content .= $chunk; |
| 277 | + } |
| 278 | + |
| 279 | + // After consuming the stream, metadata should be available |
| 280 | + $metadata = $output->getResult()->getMetadata(); |
| 281 | + $this->assertTrue($metadata->has('sources')); |
| 282 | + $this->assertCount(2, $metadata->get('sources')); |
| 283 | + $this->assertSame([$source1, $source2], $metadata->get('sources')); |
| 284 | + } |
236 | 285 | } |
0 commit comments