Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions examples/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
use Symfony\AI\Platform\Exception\ExceptionInterface as PlatformException;
use Symfony\AI\Platform\Metadata\Metadata;
use Symfony\AI\Platform\Metadata\TokenUsage;
use Symfony\AI\Platform\Result\ResultPromise;
use Symfony\AI\Platform\Result\DeferredResult;
use Symfony\AI\Store\Exception\ExceptionInterface as StoreException;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Logger\ConsoleLogger;
Expand Down Expand Up @@ -120,7 +120,7 @@ function print_token_usage(Metadata $metadata): void
$table->render();
}

function print_vectors(ResultPromise $result): void
function print_vectors(DeferredResult $result): void
{
assert([] !== $result->asVectors());
assert(array_key_exists(0, $result->asVectors()));
Expand Down Expand Up @@ -178,7 +178,7 @@ function perplexity_print_citations(Metadata $metadata): void
}
}

function print_stream(ResultPromise $result): void
function print_stream(DeferredResult $result): void
{
foreach ($result->asStream() as $word) {
echo $word;
Expand Down
13 changes: 7 additions & 6 deletions src/agent/tests/AgentTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\AI\Platform\Message\UserMessage;
use Symfony\AI\Platform\PlatformInterface;
use Symfony\AI\Platform\Result\DeferredResult;
use Symfony\AI\Platform\Result\RawResultInterface;
use Symfony\AI\Platform\Result\ResultInterface;
use Symfony\AI\Platform\Result\ResultPromise;
use Symfony\AI\Platform\Test\PlainConverter;

final class AgentTest extends TestCase
{
Expand Down Expand Up @@ -120,7 +121,7 @@ public function testCallProcessesInputThroughProcessors()
->with($this->isInstanceOf(Input::class));

$rawResult = $this->createMock(RawResultInterface::class);
$response = new ResultPromise(fn () => $result, $rawResult, []);
$response = new DeferredResult(new PlainConverter($result), $rawResult, []);

$platform->expects($this->once())
->method('invoke')
Expand All @@ -146,7 +147,7 @@ public function testCallProcessesOutputThroughProcessors()
->with($this->isInstanceOf(Output::class));

$rawResult = $this->createMock(RawResultInterface::class);
$response = new ResultPromise(fn () => $result, $rawResult, []);
$response = new DeferredResult(new PlainConverter($result), $rawResult, []);

$platform->expects($this->once())
->method('invoke')
Expand All @@ -166,7 +167,7 @@ public function testCallAllowsAudioInputWithSupport()
$result = $this->createMock(ResultInterface::class);

$rawResult = $this->createMock(RawResultInterface::class);
$response = new ResultPromise(fn () => $result, $rawResult, []);
$response = new DeferredResult(new PlainConverter($result), $rawResult, []);

$platform->expects($this->once())
->method('invoke')
Expand All @@ -186,7 +187,7 @@ public function testCallAllowsImageInputWithSupport()
$result = $this->createMock(ResultInterface::class);

$rawResult = $this->createMock(RawResultInterface::class);
$response = new ResultPromise(fn () => $result, $rawResult, []);
$response = new DeferredResult(new PlainConverter($result), $rawResult, []);

$platform->expects($this->once())
->method('invoke')
Expand All @@ -207,7 +208,7 @@ public function testCallPassesOptionsToInvoke()
$result = $this->createMock(ResultInterface::class);

$rawResult = $this->createMock(RawResultInterface::class);
$response = new ResultPromise(fn () => $result, $rawResult, []);
$response = new DeferredResult(new PlainConverter($result), $rawResult, []);

$platform->expects($this->once())
->method('invoke')
Expand Down
15 changes: 8 additions & 7 deletions src/agent/tests/Memory/EmbeddingProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\AI\Platform\Model;
use Symfony\AI\Platform\PlatformInterface;
use Symfony\AI\Platform\Result\DeferredResult;
use Symfony\AI\Platform\Result\RawResultInterface;
use Symfony\AI\Platform\Result\ResultPromise;
use Symfony\AI\Platform\Result\VectorResult;
use Symfony\AI\Platform\Test\PlainConverter;
use Symfony\AI\Platform\Vector\Vector;
use Symfony\AI\Store\StoreInterface;

Expand Down Expand Up @@ -78,16 +79,16 @@ public function testItIsDoingNothingWhenUserMessageHasNoTextContent()
public function testItIsNotCreatingMemoryWhenNoVectorsFound()
{
$vectorResult = new VectorResult($vector = new Vector([0.1, 0.2], 2));
$resultPromise = new ResultPromise(
static fn () => $vectorResult,
$deferredResult = new DeferredResult(
new PlainConverter($vectorResult),
$this->createStub(RawResultInterface::class),
);

$platform = $this->createMock(PlatformInterface::class);
$platform->expects($this->once())
->method('invoke')
->with('text-embedding-3-small', 'Have we talked about the weather?')
->willReturn($resultPromise);
->willReturn($deferredResult);

$store = $this->createMock(StoreInterface::class);
$store->expects($this->once())
Expand All @@ -109,16 +110,16 @@ public function testItIsNotCreatingMemoryWhenNoVectorsFound()
public function testItIsCreatingMemoryWithFoundVectors()
{
$vectorResult = new VectorResult($vector = new Vector([0.1, 0.2], 2));
$resultPromise = new ResultPromise(
static fn () => $vectorResult,
$deferredResult = new DeferredResult(
new PlainConverter($vectorResult),
$this->createStub(RawResultInterface::class),
);

$platform = $this->createMock(PlatformInterface::class);
$platform->expects($this->once())
->method('invoke')
->with('text-embedding-3-small', 'Have we talked about the weather?')
->willReturn($resultPromise);
->willReturn($deferredResult);

$store = $this->createMock(StoreInterface::class);
$store->expects($this->once())
Expand Down
3 changes: 1 addition & 2 deletions src/ai-bundle/src/Command/PlatformInvokeCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$messages = new MessageBag();
$messages->add(Message::ofUser($this->message));

$resultPromise = $this->platform->invoke($this->model, $messages);
$result = $resultPromise->getResult();
$result = $this->platform->invoke($this->model, $messages)->getResult();

if ($result instanceof TextResult) {
$io->writeln('<info>Response:</info> '.$result->getContent());
Expand Down
2 changes: 1 addition & 1 deletion src/ai-bundle/src/Profiler/DataCollector.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ private function awaitCallResults(TraceablePlatform $platform): array
{
$calls = $platform->calls;
foreach ($calls as $key => $call) {
$result = $call['result']->await();
$result = $call['result']->getResult();

if (isset($platform->resultCache[$result])) {
$call['result'] = $platform->resultCache[$result];
Expand Down
17 changes: 9 additions & 8 deletions src/ai-bundle/src/Profiler/TraceablePlatform.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@
use Symfony\AI\Platform\Model;
use Symfony\AI\Platform\ModelCatalog\ModelCatalogInterface;
use Symfony\AI\Platform\PlatformInterface;
use Symfony\AI\Platform\Result\DeferredResult;
use Symfony\AI\Platform\Result\ResultInterface;
use Symfony\AI\Platform\Result\ResultPromise;
use Symfony\AI\Platform\Result\StreamResult;
use Symfony\AI\Platform\Test\PlainConverter;

/**
* @author Christopher Hertel <[email protected]>
Expand All @@ -26,7 +27,7 @@
* model: string,
* input: array<mixed>|string|object,
* options: array<string, mixed>,
* result: ResultPromise,
* result: DeferredResult,
* }
*/
final class TraceablePlatform implements PlatformInterface
Expand All @@ -46,27 +47,27 @@ public function __construct(
$this->resultCache = new \WeakMap();
}

public function invoke(string $model, array|string|object $input, array $options = []): ResultPromise
public function invoke(string $model, array|string|object $input, array $options = []): DeferredResult
{
$resultPromise = $this->platform->invoke($model, $input, $options);
$deferredResult = $this->platform->invoke($model, $input, $options);

if ($input instanceof File) {
$input = $input::class.': '.$input->getFormat();
}

if ($options['stream'] ?? false) {
$originalStream = $resultPromise->asStream();
$resultPromise = new ResultPromise(fn () => $this->createTraceableStreamResult($originalStream), $resultPromise->getRawResult(), $options);
$originalStream = $deferredResult->asStream();
$deferredResult = new DeferredResult(new PlainConverter($this->createTraceableStreamResult($originalStream)), $deferredResult->getRawResult(), $options);
}

$this->calls[] = [
'model' => $model,
'input' => \is_object($input) ? clone $input : $input,
'options' => $options,
'result' => $resultPromise,
'result' => $deferredResult,
];

return $resultPromise;
return $deferredResult;
}

public function getModelCatalog(): ModelCatalogInterface
Expand Down
5 changes: 3 additions & 2 deletions src/ai-bundle/tests/Command/PlatformInvokeCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@
use Symfony\AI\AiBundle\Command\PlatformInvokeCommand;
use Symfony\AI\AiBundle\Exception\InvalidArgumentException;
use Symfony\AI\Platform\PlatformInterface;
use Symfony\AI\Platform\Result\DeferredResult;
use Symfony\AI\Platform\Result\InMemoryRawResult;
use Symfony\AI\Platform\Result\ResultPromise;
use Symfony\AI\Platform\Result\TextResult;
use Symfony\AI\Platform\Test\PlainConverter;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Component\DependencyInjection\ServiceLocator;
Expand All @@ -28,7 +29,7 @@ public function testExecuteSuccessfully()
{
$textResult = new TextResult('Hello! How can I assist you?');
$rawResult = new InMemoryRawResult([]);
$promise = new ResultPromise(fn () => $textResult, $rawResult);
$promise = new DeferredResult(new PlainConverter($textResult), $rawResult);

$platform = $this->createMock(PlatformInterface::class);
$platform->method('invoke')
Expand Down
7 changes: 4 additions & 3 deletions src/ai-bundle/tests/Profiler/DataCollectorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@
use Symfony\AI\Platform\Message\Message;
use Symfony\AI\Platform\Message\MessageBag;
use Symfony\AI\Platform\PlatformInterface;
use Symfony\AI\Platform\Result\DeferredResult;
use Symfony\AI\Platform\Result\RawResultInterface;
use Symfony\AI\Platform\Result\ResultPromise;
use Symfony\AI\Platform\Result\StreamResult;
use Symfony\AI\Platform\Result\TextResult;
use Symfony\AI\Platform\Test\PlainConverter;

class DataCollectorTest extends TestCase
{
Expand All @@ -33,7 +34,7 @@ public function testCollectsDataForNonStreamingResponse()
$messageBag = new MessageBag(Message::ofUser(new Text('Hello')));
$result = new TextResult('Assistant response');

$platform->method('invoke')->willReturn(new ResultPromise(static fn () => $result, $this->createStub(RawResultInterface::class)));
$platform->method('invoke')->willReturn(new DeferredResult(new PlainConverter($result), $this->createStub(RawResultInterface::class)));

$result = $traceablePlatform->invoke('gpt-4o', $messageBag, ['stream' => false]);
$this->assertSame('Assistant response', $result->asText());
Expand All @@ -57,7 +58,7 @@ public function testCollectsDataForStreamingResponse()
})(),
);

$platform->method('invoke')->willReturn(new ResultPromise(static fn () => $result, $this->createStub(RawResultInterface::class)));
$platform->method('invoke')->willReturn(new DeferredResult(new PlainConverter($result), $this->createStub(RawResultInterface::class)));

$result = $traceablePlatform->invoke('gpt-4o', $messageBag, ['stream' => true]);
$this->assertSame('Assistant response', implode('', iterator_to_array($result->asStream())));
Expand Down
8 changes: 4 additions & 4 deletions src/platform/src/Platform.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@

use Symfony\AI\Platform\Exception\RuntimeException;
use Symfony\AI\Platform\ModelCatalog\ModelCatalogInterface;
use Symfony\AI\Platform\Result\DeferredResult;
use Symfony\AI\Platform\Result\RawResultInterface;
use Symfony\AI\Platform\Result\ResultPromise;

/**
* @author Christopher Hertel <[email protected]>
Expand Down Expand Up @@ -46,7 +46,7 @@ public function __construct(
$this->resultConverters = $resultConverters instanceof \Traversable ? iterator_to_array($resultConverters) : $resultConverters;
}

public function invoke(string $model, array|string|object $input, array $options = []): ResultPromise
public function invoke(string $model, array|string|object $input, array $options = []): DeferredResult
{
$model = $this->modelCatalog->getModel($model);
$payload = $this->contract->createRequestPayload($model, $input);
Expand Down Expand Up @@ -84,11 +84,11 @@ private function doInvoke(Model $model, array|string $payload, array $options =
/**
* @param array<string, mixed> $options
*/
private function convertResult(Model $model, RawResultInterface $result, array $options): ResultPromise
private function convertResult(Model $model, RawResultInterface $result, array $options): DeferredResult
{
foreach ($this->resultConverters as $resultConverter) {
if ($resultConverter->supports($model)) {
return new ResultPromise($resultConverter->convert(...), $result, $options);
return new DeferredResult($resultConverter, $result, $options);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/platform/src/PlatformInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
namespace Symfony\AI\Platform;

use Symfony\AI\Platform\ModelCatalog\ModelCatalogInterface;
use Symfony\AI\Platform\Result\ResultPromise;
use Symfony\AI\Platform\Result\DeferredResult;

/**
* @author Christopher Hertel <[email protected]>
Expand All @@ -24,7 +24,7 @@ interface PlatformInterface
* @param array<mixed>|string|object $input The input data
* @param array<string, mixed> $options The options to customize the model invocation
*/
public function invoke(string $model, array|string|object $input, array $options = []): ResultPromise;
public function invoke(string $model, array|string|object $input, array $options = []): DeferredResult;

public function getModelCatalog(): ModelCatalogInterface;
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@

use Symfony\AI\Platform\Exception\ExceptionInterface;
use Symfony\AI\Platform\Exception\UnexpectedResultTypeException;
use Symfony\AI\Platform\ResultConverterInterface;
use Symfony\AI\Platform\Vector\Vector;

/**
* @author Christopher Hertel <[email protected]>
*/
final class ResultPromise
final class DeferredResult
{
private bool $isConverted = false;
private ResultInterface $convertedResult;
Expand All @@ -27,7 +28,7 @@ final class ResultPromise
* @param array<string, mixed> $options
*/
public function __construct(
private readonly \Closure $resultConverter,
private readonly ResultConverterInterface $resultConverter,
private readonly RawResultInterface $rawResult,
private readonly array $options = [],
) {
Expand All @@ -37,22 +38,9 @@ public function __construct(
* @throws ExceptionInterface
*/
public function getResult(): ResultInterface
{
return $this->await();
}

public function getRawResult(): RawResultInterface
{
return $this->rawResult;
}

/**
* @throws ExceptionInterface
*/
public function await(): ResultInterface
{
if (!$this->isConverted) {
$this->convertedResult = ($this->resultConverter)($this->rawResult, $this->options);
$this->convertedResult = $this->resultConverter->convert($this->rawResult, $this->options);

if (null === $this->convertedResult->getRawResult()) {
// Fallback to set the raw result when it was not handled by the ResultConverter itself
Expand All @@ -65,6 +53,11 @@ public function await(): ResultInterface
return $this->convertedResult;
}

public function getRawResult(): RawResultInterface
{
return $this->rawResult;
}

/**
* @throws ExceptionInterface
*/
Expand Down
Loading