Skip to content

Commit 9a87f20

Browse files
committed
Rename to DeferredResult and explicit contract instead of closure
1 parent c4b5c59 commit 9a87f20

File tree

14 files changed

+90
-61
lines changed

14 files changed

+90
-61
lines changed

examples/bootstrap.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
use Symfony\AI\Platform\Exception\ExceptionInterface as PlatformException;
1616
use Symfony\AI\Platform\Metadata\Metadata;
1717
use Symfony\AI\Platform\Metadata\TokenUsage;
18-
use Symfony\AI\Platform\Result\ResultPromise;
18+
use Symfony\AI\Platform\Result\DeferredResult;
1919
use Symfony\AI\Store\Exception\ExceptionInterface as StoreException;
2020
use Symfony\Component\Console\Helper\Table;
2121
use Symfony\Component\Console\Logger\ConsoleLogger;
@@ -120,7 +120,7 @@ function print_token_usage(Metadata $metadata): void
120120
$table->render();
121121
}
122122

123-
function print_vectors(ResultPromise $result): void
123+
function print_vectors(DeferredResult $result): void
124124
{
125125
assert([] !== $result->asVectors());
126126
assert(array_key_exists(0, $result->asVectors()));
@@ -178,7 +178,7 @@ function perplexity_print_citations(Metadata $metadata): void
178178
}
179179
}
180180

181-
function print_stream(ResultPromise $result): void
181+
function print_stream(DeferredResult $result): void
182182
{
183183
foreach ($result->asStream() as $word) {
184184
echo $word;

src/agent/tests/AgentTest.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
use Symfony\AI\Platform\PlatformInterface;
2929
use Symfony\AI\Platform\Result\RawResultInterface;
3030
use Symfony\AI\Platform\Result\ResultInterface;
31-
use Symfony\AI\Platform\Result\ResultPromise;
31+
use Symfony\AI\Platform\Result\DeferredResult;
32+
use Symfony\AI\Platform\Test\PlainConverter;
3233

3334
final class AgentTest extends TestCase
3435
{
@@ -120,7 +121,7 @@ public function testCallProcessesInputThroughProcessors()
120121
->with($this->isInstanceOf(Input::class));
121122

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

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

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

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

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

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

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

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

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

212213
$platform->expects($this->once())
213214
->method('invoke')

src/agent/tests/Memory/EmbeddingProviderTest.php

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@
2121
use Symfony\AI\Platform\Model;
2222
use Symfony\AI\Platform\PlatformInterface;
2323
use Symfony\AI\Platform\Result\RawResultInterface;
24-
use Symfony\AI\Platform\Result\ResultPromise;
24+
use Symfony\AI\Platform\Result\DeferredResult;
2525
use Symfony\AI\Platform\Result\VectorResult;
26+
use Symfony\AI\Platform\Test\PlainConverter;
2627
use Symfony\AI\Platform\Vector\Vector;
2728
use Symfony\AI\Store\StoreInterface;
2829

@@ -78,8 +79,8 @@ public function testItIsDoingNothingWhenUserMessageHasNoTextContent()
7879
public function testItIsNotCreatingMemoryWhenNoVectorsFound()
7980
{
8081
$vectorResult = new VectorResult($vector = new Vector([0.1, 0.2], 2));
81-
$resultPromise = new ResultPromise(
82-
static fn () => $vectorResult,
82+
$resultPromise = new DeferredResult(
83+
new PlainConverter($vectorResult),
8384
$this->createStub(RawResultInterface::class),
8485
);
8586

@@ -109,8 +110,8 @@ public function testItIsNotCreatingMemoryWhenNoVectorsFound()
109110
public function testItIsCreatingMemoryWithFoundVectors()
110111
{
111112
$vectorResult = new VectorResult($vector = new Vector([0.1, 0.2], 2));
112-
$resultPromise = new ResultPromise(
113-
static fn () => $vectorResult,
113+
$resultPromise = new DeferredResult(
114+
new PlainConverter($vectorResult),
114115
$this->createStub(RawResultInterface::class),
115116
);
116117

src/ai-bundle/src/Profiler/TraceablePlatform.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@
1616
use Symfony\AI\Platform\ModelCatalog\ModelCatalogInterface;
1717
use Symfony\AI\Platform\PlatformInterface;
1818
use Symfony\AI\Platform\Result\ResultInterface;
19-
use Symfony\AI\Platform\Result\ResultPromise;
19+
use Symfony\AI\Platform\Result\DeferredResult;
2020
use Symfony\AI\Platform\Result\StreamResult;
21+
use Symfony\AI\Platform\Test\PlainConverter;
2122

2223
/**
2324
* @author Christopher Hertel <[email protected]>
@@ -26,7 +27,7 @@
2627
* model: string,
2728
* input: array<mixed>|string|object,
2829
* options: array<string, mixed>,
29-
* result: ResultPromise,
30+
* result: DeferredResult,
3031
* }
3132
*/
3233
final class TraceablePlatform implements PlatformInterface
@@ -46,7 +47,7 @@ public function __construct(
4647
$this->resultCache = new \WeakMap();
4748
}
4849

49-
public function invoke(string $model, array|string|object $input, array $options = []): ResultPromise
50+
public function invoke(string $model, array|string|object $input, array $options = []): DeferredResult
5051
{
5152
$resultPromise = $this->platform->invoke($model, $input, $options);
5253

@@ -56,7 +57,7 @@ public function invoke(string $model, array|string|object $input, array $options
5657

5758
if ($options['stream'] ?? false) {
5859
$originalStream = $resultPromise->asStream();
59-
$resultPromise = new ResultPromise(fn () => $this->createTraceableStreamResult($originalStream), $resultPromise->getRawResult(), $options);
60+
$resultPromise = new DeferredResult(new PlainConverter($this->createTraceableStreamResult($originalStream)), $resultPromise->getRawResult(), $options);
6061
}
6162

6263
$this->calls[] = [

src/ai-bundle/tests/Command/PlatformInvokeCommandTest.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@
1616
use Symfony\AI\AiBundle\Exception\InvalidArgumentException;
1717
use Symfony\AI\Platform\PlatformInterface;
1818
use Symfony\AI\Platform\Result\InMemoryRawResult;
19-
use Symfony\AI\Platform\Result\ResultPromise;
19+
use Symfony\AI\Platform\Result\DeferredResult;
2020
use Symfony\AI\Platform\Result\TextResult;
21+
use Symfony\AI\Platform\Test\PlainConverter;
2122
use Symfony\Component\Console\Command\Command;
2223
use Symfony\Component\Console\Tester\CommandTester;
2324
use Symfony\Component\DependencyInjection\ServiceLocator;
@@ -28,7 +29,7 @@ public function testExecuteSuccessfully()
2829
{
2930
$textResult = new TextResult('Hello! How can I assist you?');
3031
$rawResult = new InMemoryRawResult([]);
31-
$promise = new ResultPromise(fn () => $textResult, $rawResult);
32+
$promise = new DeferredResult(new PlainConverter($textResult), $rawResult);
3233

3334
$platform = $this->createMock(PlatformInterface::class);
3435
$platform->method('invoke')

src/ai-bundle/tests/Profiler/DataCollectorTest.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@
2020
use Symfony\AI\Platform\Message\MessageBag;
2121
use Symfony\AI\Platform\PlatformInterface;
2222
use Symfony\AI\Platform\Result\RawResultInterface;
23-
use Symfony\AI\Platform\Result\ResultPromise;
23+
use Symfony\AI\Platform\Result\DeferredResult;
2424
use Symfony\AI\Platform\Result\StreamResult;
2525
use Symfony\AI\Platform\Result\TextResult;
26+
use Symfony\AI\Platform\Test\PlainConverter;
2627

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

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

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

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

6263
$result = $traceablePlatform->invoke('gpt-4o', $messageBag, ['stream' => true]);
6364
$this->assertSame('Assistant response', implode('', iterator_to_array($result->asStream())));

src/platform/src/Platform.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
use Symfony\AI\Platform\Exception\RuntimeException;
1515
use Symfony\AI\Platform\ModelCatalog\ModelCatalogInterface;
1616
use Symfony\AI\Platform\Result\RawResultInterface;
17-
use Symfony\AI\Platform\Result\ResultPromise;
17+
use Symfony\AI\Platform\Result\DeferredResult;
1818

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

49-
public function invoke(string $model, array|string|object $input, array $options = []): ResultPromise
49+
public function invoke(string $model, array|string|object $input, array $options = []): DeferredResult
5050
{
5151
$model = $this->modelCatalog->getModel($model);
5252
$payload = $this->contract->createRequestPayload($model, $input);
@@ -84,11 +84,11 @@ private function doInvoke(Model $model, array|string $payload, array $options =
8484
/**
8585
* @param array<string, mixed> $options
8686
*/
87-
private function convertResult(Model $model, RawResultInterface $result, array $options): ResultPromise
87+
private function convertResult(Model $model, RawResultInterface $result, array $options): DeferredResult
8888
{
8989
foreach ($this->resultConverters as $resultConverter) {
9090
if ($resultConverter->supports($model)) {
91-
return new ResultPromise($resultConverter->convert(...), $result, $options);
91+
return new DeferredResult($resultConverter, $result, $options);
9292
}
9393
}
9494

src/platform/src/PlatformInterface.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
namespace Symfony\AI\Platform;
1313

1414
use Symfony\AI\Platform\ModelCatalog\ModelCatalogInterface;
15-
use Symfony\AI\Platform\Result\ResultPromise;
15+
use Symfony\AI\Platform\Result\DeferredResult;
1616

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

2929
public function getModelCatalog(): ModelCatalogInterface;
3030
}

src/platform/src/Result/ResultPromise.php renamed to src/platform/src/Result/DeferredResult.php

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,13 @@
1313

1414
use Symfony\AI\Platform\Exception\ExceptionInterface;
1515
use Symfony\AI\Platform\Exception\UnexpectedResultTypeException;
16+
use Symfony\AI\Platform\ResultConverterInterface;
1617
use Symfony\AI\Platform\Vector\Vector;
1718

1819
/**
1920
* @author Christopher Hertel <[email protected]>
2021
*/
21-
final class ResultPromise
22+
final class DeferredResult
2223
{
2324
private bool $isConverted = false;
2425
private ResultInterface $convertedResult;
@@ -27,7 +28,7 @@ final class ResultPromise
2728
* @param array<string, mixed> $options
2829
*/
2930
public function __construct(
30-
private readonly \Closure $resultConverter,
31+
private readonly ResultConverterInterface $resultConverter,
3132
private readonly RawResultInterface $rawResult,
3233
private readonly array $options = [],
3334
) {
@@ -37,22 +38,9 @@ public function __construct(
3738
* @throws ExceptionInterface
3839
*/
3940
public function getResult(): ResultInterface
40-
{
41-
return $this->await();
42-
}
43-
44-
public function getRawResult(): RawResultInterface
45-
{
46-
return $this->rawResult;
47-
}
48-
49-
/**
50-
* @throws ExceptionInterface
51-
*/
52-
public function await(): ResultInterface
5341
{
5442
if (!$this->isConverted) {
55-
$this->convertedResult = ($this->resultConverter)($this->rawResult, $this->options);
43+
$this->convertedResult = $this->resultConverter->convert($this->rawResult, $this->options);
5644

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

56+
public function getRawResult(): RawResultInterface
57+
{
58+
return $this->rawResult;
59+
}
60+
6861
/**
6962
* @throws ExceptionInterface
7063
*/

src/platform/src/InMemoryPlatform.php renamed to src/platform/src/Test/InMemoryPlatform.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@
99
* file that was distributed with this source code.
1010
*/
1111

12-
namespace Symfony\AI\Platform;
12+
namespace Symfony\AI\Platform\Test;
1313

14+
use Symfony\AI\Platform\Model;
1415
use Symfony\AI\Platform\ModelCatalog\DynamicModelCatalog;
1516
use Symfony\AI\Platform\ModelCatalog\ModelCatalogInterface;
17+
use Symfony\AI\Platform\PlatformInterface;
18+
use Symfony\AI\Platform\Result\DeferredResult;
1619
use Symfony\AI\Platform\Result\InMemoryRawResult;
1720
use Symfony\AI\Platform\Result\ResultInterface;
18-
use Symfony\AI\Platform\Result\ResultPromise;
1921
use Symfony\AI\Platform\Result\TextResult;
2022

2123
/**
@@ -38,7 +40,7 @@ public function __construct(private readonly \Closure|string $mockResult)
3840
$this->modelCatalog = new DynamicModelCatalog();
3941
}
4042

41-
public function invoke(string $model, array|string|object $input, array $options = []): ResultPromise
43+
public function invoke(string $model, array|string|object $input, array $options = []): DeferredResult
4244
{
4345
$model = new class($model) extends Model {
4446
public function __construct(string $name)
@@ -66,13 +68,13 @@ public function getModelCatalog(): ModelCatalogInterface
6668
* @param ResultInterface $result The result to wrap in a promise
6769
* @param array<string, mixed> $options Additional options for the promise
6870
*/
69-
private function createPromise(ResultInterface $result, array $options): ResultPromise
71+
private function createPromise(ResultInterface $result, array $options): DeferredResult
7072
{
7173
$rawResult = $result->getRawResult() ?? new InMemoryRawResult(
7274
['text' => $result->getContent()],
7375
(object) ['text' => $result->getContent()],
7476
);
7577

76-
return new ResultPromise(static fn () => $result, $rawResult, $options);
78+
return new DeferredResult(new PlainConverter($result), $rawResult, $options);
7779
}
7880
}

0 commit comments

Comments
 (0)