Skip to content

Commit ed6eaea

Browse files
committed
Use JSON Path to convert responses
1 parent f1870bc commit ed6eaea

File tree

7 files changed

+50
-53
lines changed

7 files changed

+50
-53
lines changed

examples/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"symfony/event-dispatcher": "^6.4|^7.0",
2323
"symfony/filesystem": "^6.4|^7.0",
2424
"symfony/finder": "^6.4|^7.0",
25+
"symfony/json-path": "^7.3",
2526
"symfony/process": "^6.4|^7.0",
2627
"symfony/var-dumper": "^6.4|^7.0"
2728
},

src/platform/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"psr/log": "^3.0",
2929
"symfony/clock": "^6.4 || ^7.1",
3030
"symfony/http-client": "^6.4 || ^7.1",
31+
"symfony/json-path": "^7.3",
3132
"symfony/property-access": "^6.4 || ^7.1",
3233
"symfony/property-info": "^6.4 || ^7.1",
3334
"symfony/serializer": "^6.4 || ^7.1",

src/platform/src/Bridge/Google/Embeddings/ResponseConverter.php

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,10 @@
1212
namespace Symfony\AI\Platform\Bridge\Google\Embeddings;
1313

1414
use Symfony\AI\Platform\Bridge\Google\Embeddings;
15-
use Symfony\AI\Platform\Exception\RuntimeException;
15+
use Symfony\AI\Platform\Contract\ResponseConverter\VectorResponseConverter;
1616
use Symfony\AI\Platform\Model;
1717
use Symfony\AI\Platform\Response\VectorResponse;
1818
use Symfony\AI\Platform\ResponseConverterInterface;
19-
use Symfony\AI\Platform\Vector\Vector;
2019
use Symfony\Contracts\HttpClient\ResponseInterface;
2120

2221
/**
@@ -31,17 +30,6 @@ public function supports(Model $model): bool
3130

3231
public function convert(ResponseInterface $response, array $options = []): VectorResponse
3332
{
34-
$data = $response->toArray();
35-
36-
if (!isset($data['embeddings'])) {
37-
throw new RuntimeException('Response does not contain data');
38-
}
39-
40-
return new VectorResponse(
41-
...array_map(
42-
static fn (array $item): Vector => new Vector($item['values']),
43-
$data['embeddings'],
44-
),
45-
);
33+
return (new VectorResponseConverter('$.embeddings[*].values'))($response->getContent(false));
4634
}
4735
}

src/platform/src/Bridge/Mistral/Embeddings/ResponseConverter.php

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

1414
use Symfony\AI\Platform\Bridge\Mistral\Embeddings;
15+
use Symfony\AI\Platform\Contract\ResponseConverter\VectorResponseConverter;
1516
use Symfony\AI\Platform\Exception\RuntimeException;
1617
use Symfony\AI\Platform\Model;
1718
use Symfony\AI\Platform\Response\VectorResponse;
1819
use Symfony\AI\Platform\ResponseConverterInterface;
19-
use Symfony\AI\Platform\Vector\Vector;
2020
use Symfony\Contracts\HttpClient\ResponseInterface;
2121

2222
/**
@@ -31,21 +31,10 @@ public function supports(Model $model): bool
3131

3232
public function convert(ResponseInterface $response, array $options = []): VectorResponse
3333
{
34-
$data = $response->toArray(false);
35-
3634
if (200 !== $response->getStatusCode()) {
3735
throw new RuntimeException(\sprintf('Unexpected response code %d: %s', $response->getStatusCode(), $response->getContent(false)));
3836
}
3937

40-
if (!isset($data['data'])) {
41-
throw new RuntimeException('Response does not contain data');
42-
}
43-
44-
return new VectorResponse(
45-
...array_map(
46-
static fn (array $item): Vector => new Vector($item['embedding']),
47-
$data['data']
48-
),
49-
);
38+
return (new VectorResponseConverter())($response->getContent(false));
5039
}
5140
}

src/platform/src/Bridge/OpenAI/Embeddings/ResponseConverter.php

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,10 @@
1212
namespace Symfony\AI\Platform\Bridge\OpenAI\Embeddings;
1313

1414
use Symfony\AI\Platform\Bridge\OpenAI\Embeddings;
15-
use Symfony\AI\Platform\Exception\RuntimeException;
15+
use Symfony\AI\Platform\Contract\ResponseConverter\VectorResponseConverter;
1616
use Symfony\AI\Platform\Model;
1717
use Symfony\AI\Platform\Response\VectorResponse;
1818
use Symfony\AI\Platform\ResponseConverterInterface as PlatformResponseConverter;
19-
use Symfony\AI\Platform\Vector\Vector;
2019
use Symfony\Contracts\HttpClient\ResponseInterface;
2120

2221
/**
@@ -31,17 +30,6 @@ public function supports(Model $model): bool
3130

3231
public function convert(ResponseInterface $response, array $options = []): VectorResponse
3332
{
34-
$data = $response->toArray();
35-
36-
if (!isset($data['data'])) {
37-
throw new RuntimeException('Response does not contain data');
38-
}
39-
40-
return new VectorResponse(
41-
...array_map(
42-
static fn (array $item): Vector => new Vector($item['embedding']),
43-
$data['data']
44-
),
45-
);
33+
return (new VectorResponseConverter())($response->getContent(false));
4634
}
4735
}

src/platform/src/Bridge/Voyage/ResponseConverter.php

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,10 @@
1111

1212
namespace Symfony\AI\Platform\Bridge\Voyage;
1313

14-
use Symfony\AI\Platform\Exception\RuntimeException;
14+
use Symfony\AI\Platform\Contract\ResponseConverter\VectorResponseConverter;
1515
use Symfony\AI\Platform\Model;
1616
use Symfony\AI\Platform\Response\ResponseInterface as LlmResponse;
17-
use Symfony\AI\Platform\Response\VectorResponse;
1817
use Symfony\AI\Platform\ResponseConverterInterface;
19-
use Symfony\AI\Platform\Vector\Vector;
2018
use Symfony\Contracts\HttpClient\ResponseInterface;
2119

2220
/**
@@ -31,14 +29,6 @@ public function supports(Model $model): bool
3129

3230
public function convert(ResponseInterface $response, array $options = []): LlmResponse
3331
{
34-
$response = $response->toArray();
35-
36-
if (!isset($response['data'])) {
37-
throw new RuntimeException('Response does not contain embedding data');
38-
}
39-
40-
$vectors = array_map(fn (array $data) => new Vector($data['embedding']), $response['data']);
41-
42-
return new VectorResponse($vectors[0]);
32+
return (new VectorResponseConverter())($response->getContent(false));
4333
}
4434
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\AI\Platform\Contract\ResponseConverter;
13+
14+
use Symfony\AI\Platform\Exception\RuntimeException;
15+
use Symfony\AI\Platform\Response\VectorResponse;
16+
use Symfony\AI\Platform\Vector\Vector;
17+
use Symfony\Component\JsonPath\JsonCrawler;
18+
use Symfony\Component\JsonPath\JsonPath;
19+
20+
final readonly class VectorResponseConverter
21+
{
22+
public function __construct(
23+
private string|JsonPath $query = '$.data[*].embedding',
24+
) {
25+
}
26+
27+
public function __invoke(string $json): VectorResponse
28+
{
29+
$crawler = new JsonCrawler($json);
30+
$vectors = $crawler->find($this->query);
31+
32+
if (empty($vectors)) {
33+
throw new RuntimeException('Response does not contain any vectors');
34+
}
35+
36+
return new VectorResponse(
37+
...array_map(static fn (array $vector): Vector => new Vector($vector), $vectors),
38+
);
39+
}
40+
}

0 commit comments

Comments
 (0)