Skip to content

Commit 9265cbc

Browse files
committed
feature #252 [Platform] Enhance in memory platform to support all ResultInterface types (RamyHakam)
This PR was squashed before being merged into the main branch. Discussion ---------- [Platform] Enhance in memory platform to support all `ResultInterface` types | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes <!-- please update src/**/CHANGELOG.md files --> | Docs? | yes <!-- required for new features --> | Issues | none <!-- prefix each issue number with "Fix #", no need to create an issue if none exist, explain below instead --> | License | MIT Enhances the existing `InMemoryPlatform` to support all `ResultInterface` types, making it easier to test all result types. Previously limited to text responses, it now supports vectors, images, binary data, choices, and any custom result types. Commits ------- 82e873f [Platform] Enhance in memory platform to support all `ResultInterface` types
2 parents 320fcd6 + 82e873f commit 9265cbc

File tree

3 files changed

+72
-16
lines changed

3 files changed

+72
-16
lines changed

src/platform/doc/index.rst

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ For unit or integration testing, you can use the `InMemoryPlatform`, which imple
289289
It supports returning either:
290290

291291
- A fixed string result
292-
- A callable that dynamically returns a response based on the model, input, and options::
292+
- A callable that dynamically returns a simple string or any ``ResultInterface`` based on the model, input, and options::
293293

294294
use Symfony\AI\Platform\InMemoryPlatform;
295295
use Symfony\AI\Platform\Model;
@@ -300,8 +300,41 @@ It supports returning either:
300300

301301
echo $result->asText(); // "Fake result"
302302

303+
**Dynamic Text Results**::
303304

304-
Internally, it uses `InMemoryRawResult` to simulate the behavior of real API responses and support `ResultPromise`.
305+
$platform = new InMemoryPlatform(
306+
fn($model, $input, $options) => "Echo: {$input}"
307+
);
308+
309+
$result = $platform->invoke(new Model('test'), 'Hello AI');
310+
echo $result->asText(); // "Echo: Hello AI"
311+
312+
**Vector Results**::
313+
314+
use Symfony\AI\Platform\Result\VectorResult;
315+
316+
$platform = new InMemoryPlatform(
317+
fn() => new VectorResult(new Vector([0.1, 0.2, 0.3, 0.4]))
318+
);
319+
320+
$result = $platform->invoke(new Model('test'), 'vectorize this text');
321+
$vectors = $result->asVectors(); // Returns Vector object with [0.1, 0.2, 0.3, 0.4]
322+
323+
**Binary Results**::
324+
325+
use Symfony\AI\Platform\Result\BinaryResult;
326+
327+
$platform = new InMemoryPlatform(
328+
fn() => new BinaryResult('fake-pdf-content', 'application/pdf')
329+
);
330+
331+
$result = $platform->invoke(new Model('test'), 'generate PDF document');
332+
$binary = $result->asBinary(); // Returns Binary object with content and MIME type
333+
334+
335+
**Raw Results**
336+
337+
The platform automatically uses the ``getRawResult()`` from any ``ResultInterface`` returned by closures. For string results, it creates an ``InMemoryRawResult`` to simulate real API response metadata.
305338

306339
This allows fast and isolated testing of AI-powered features without relying on live providers or HTTP requests.
307340

src/platform/src/InMemoryPlatform.php

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

1414
use Symfony\AI\Platform\Result\InMemoryRawResult;
15+
use Symfony\AI\Platform\Result\ResultInterface;
1516
use Symfony\AI\Platform\Result\ResultPromise;
1617
use Symfony\AI\Platform\Result\TextResult;
1718

@@ -26,27 +27,36 @@ class InMemoryPlatform implements PlatformInterface
2627
{
2728
/**
2829
* The mock result can be a string or a callable that returns a string.
29-
* If it's a closure, it receives the model, input, and optionally options as parameters like a real platform call.
30+
* If it's a closure, it receives the model, input, and optionally options as parameters like a real platform call.
3031
*/
3132
public function __construct(private readonly \Closure|string $mockResult)
3233
{
3334
}
3435

3536
public function invoke(Model $model, array|string|object $input, array $options = []): ResultPromise
3637
{
37-
$resultText = $this->mockResult instanceof \Closure
38-
? ($this->mockResult)($model, $input, $options)
39-
: $this->mockResult;
40-
41-
$textResult = new TextResult($resultText);
42-
43-
return new ResultPromise(
44-
static fn () => $textResult,
45-
rawResult: new InMemoryRawResult(
46-
['text' => $resultText],
47-
(object) ['text' => $resultText],
48-
),
49-
options: $options
38+
$result = \is_string($this->mockResult) ? $this->mockResult : ($this->mockResult)($model, $input, $options);
39+
40+
if ($result instanceof ResultInterface) {
41+
return $this->createPromise($result, $options);
42+
}
43+
44+
return $this->createPromise(new TextResult($result), $options);
45+
}
46+
47+
/**
48+
* Creates a ResultPromise from a ResultInterface.
49+
*
50+
* @param ResultInterface $result The result to wrap in a promise
51+
* @param array<string, mixed> $options Additional options for the promise
52+
*/
53+
private function createPromise(ResultInterface $result, array $options): ResultPromise
54+
{
55+
$rawResult = $result->getRawResult() ?? new InMemoryRawResult(
56+
['text' => $result->getContent()],
57+
(object) ['text' => $result->getContent()],
5058
);
59+
60+
return new ResultPromise(static fn () => $result, $rawResult, $options);
5161
}
5262
}

src/platform/tests/InMemoryPlatformTest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
use PHPUnit\Framework\TestCase;
1414
use Symfony\AI\Platform\InMemoryPlatform;
1515
use Symfony\AI\Platform\Model;
16+
use Symfony\AI\Platform\Result\VectorResult;
17+
use Symfony\AI\Platform\Vector\Vector;
1618

1719
#[CoversClass(InMemoryPlatform::class)]
1820
class InMemoryPlatformTest extends TestCase
@@ -37,4 +39,15 @@ public function testPlatformInvokeWithCallableResult()
3739

3840
$this->assertSame('DYNAMIC TEXT', $result->asText());
3941
}
42+
43+
public function testPlatformInvokeWithVectorResultResponse()
44+
{
45+
$platform = new InMemoryPlatform(
46+
fn () => new VectorResult(new Vector([0.1, 0.1, 0.5]))
47+
);
48+
49+
$result = $platform->invoke(new Model('test'), 'dynamic text');
50+
51+
$this->assertEquals([0.1, 0.1, 0.5], $result->asVectors()[0]->getData());
52+
}
4053
}

0 commit comments

Comments
 (0)