Skip to content
This repository was archived by the owner on Sep 15, 2025. It is now read-only.

Commit 4a51ab3

Browse files
committed
feat(vector-store): mariadb and postgres support fixes
1 parent d30b609 commit 4a51ab3

36 files changed

Lines changed: 292 additions & 203 deletions

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ $embeddings = $client->embeddings(
5050
model: 'text-embedding-004',
5151
dimensions: 512
5252
)
53-
)->embedding;
53+
)->embeddings;
5454
```
5555

5656
### Completion

src/Model/Completion/Tools/ToolDefinition.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
* @author bernard-ng <bernard@devscast.tech>
2323
*/
2424
#[\Attribute(\Attribute::TARGET_CLASS)]
25-
readonly class ToolDefinition
25+
final readonly class ToolDefinition
2626
{
2727
/**
2828
* @param array<ToolParameter> $parameters

src/Model/Embeddings/EmbeddingsGenerator.php

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
namespace Devscast\Lugha\Model\Embeddings;
1515

16-
use Devscast\Lugha\Provider\Service\HasEmbeddingSupport;
16+
use Devscast\Lugha\Provider\Service\HasEmbeddingsSupport;
1717
use Devscast\Lugha\Retrieval\Document;
1818

1919
/**
@@ -24,33 +24,41 @@
2424
final readonly class EmbeddingsGenerator implements EmbeddingsGeneratorInterface
2525
{
2626
public function __construct(
27-
private HasEmbeddingSupport $client,
28-
private EmbeddingsConfig $config
27+
private HasEmbeddingsSupport $client,
28+
private EmbeddingsConfig $config,
29+
private DimensionReducer $dimensionReducer = new DimensionReducer()
2930
) {
3031
}
3132

3233
#[\Override]
33-
public function embedDocuments(iterable $documents): iterable
34+
public function embedDocuments(iterable $documents, ?int $dimensions = null): iterable
3435
{
3536
foreach ($documents as $document) {
36-
yield $this->embedDocument($document);
37+
yield $this->embedDocument($document, $dimensions);
3738
}
3839
}
3940

4041
#[\Override]
41-
public function embedDocument(Document $document): Document
42+
public function embedDocument(Document $document, ?int $dimensions = null): Document
4243
{
43-
$values = $this->client->embeddings($document->content, $this->config)->embedding;
44-
$document->embeddings = Vector::from($values);
44+
$values = $this->client->embeddings($document->content, $this->config)->embeddings;
45+
$vector = Vector::from($values);
46+
47+
$document->embeddings = $dimensions !== null
48+
? $this->dimensionReducer->reduce($vector, $dimensions)
49+
: $vector;
4550

4651
return $document;
4752
}
4853

4954
#[\Override]
50-
public function embedQuery(string $query): Vector
55+
public function embedQuery(string $query, ?int $dimensions = null): Vector
5156
{
52-
$values = $this->client->embeddings($query, $this->config)->embedding;
57+
$values = $this->client->embeddings($query, $this->config)->embeddings;
58+
$vector = Vector::from($values);
5359

54-
return Vector::from($values);
60+
return $dimensions !== null
61+
? $this->dimensionReducer->reduce($vector, $dimensions)
62+
: $vector;
5563
}
5664
}

src/Model/Embeddings/EmbeddingsGeneratorInterface.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ interface EmbeddingsGeneratorInterface
4343
*
4444
* @throws ServiceIntegrationException If an error occurs during the embedding process.
4545
*/
46-
public function embedDocuments(iterable $documents): iterable;
46+
public function embedDocuments(iterable $documents, ?int $dimensions = null): iterable;
4747

4848
/**
4949
* Embed a single document by converting its content into a vector representation.
@@ -55,7 +55,7 @@ public function embedDocuments(iterable $documents): iterable;
5555
*
5656
* @throws ServiceIntegrationException If an error occurs while obtaining the embedding.
5757
*/
58-
public function embedDocument(Document $document): Document;
58+
public function embedDocument(Document $document, ?int $dimensions = null): Document;
5959

6060
/**
6161
* Embed a query string into a vector representation.
@@ -69,5 +69,5 @@ public function embedDocument(Document $document): Document;
6969
*
7070
* @throws ServiceIntegrationException If an error occurs while obtaining the embedding.
7171
*/
72-
public function embedQuery(string $query): Vector;
72+
public function embedQuery(string $query, ?int $dimensions = null): Vector;
7373
}

src/Model/Embeddings/Vector.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,22 @@ public function toString(): string
4646
return (string) $this;
4747
}
4848

49+
public function to32Bit(): string
50+
{
51+
$binary = '';
52+
foreach ($this->values as $float) {
53+
$binary .= pack('f', $float); // 'f' = 32-bit float
54+
}
55+
56+
/** @var array $unpacked */
57+
$unpacked = unpack('H*', $binary);
58+
59+
/** @var string $hex */
60+
$hex = $unpacked[1];
61+
62+
return sprintf('%s', $hex);
63+
}
64+
4965
/**
5066
* @param float[] $values
5167
*/

src/Provider/Response/EmbeddingResponse.php renamed to src/Provider/Response/EmbeddingsResponse.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,16 @@
1616
use Devscast\Lugha\Provider\Provider;
1717

1818
/**
19-
* Class EmbeddingResponse.
19+
* Class EmbeddingsResponse.
2020
*
2121
* @author bernard-ng <bernard@devscast.tech>
2222
*/
23-
final readonly class EmbeddingResponse
23+
final readonly class EmbeddingsResponse
2424
{
2525
public function __construct(
2626
public Provider $provider,
2727
public string $model,
28-
public array $embedding,
28+
public array $embeddings,
2929
public array $providerResponse = [],
3030
) {
3131
}

src/Provider/Service/Client/GoogleClient.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@
2020
use Devscast\Lugha\Model\Embeddings\EmbeddingsConfig;
2121
use Devscast\Lugha\Provider\Provider;
2222
use Devscast\Lugha\Provider\Response\CompletionResponse;
23-
use Devscast\Lugha\Provider\Response\EmbeddingResponse;
23+
use Devscast\Lugha\Provider\Response\EmbeddingsResponse;
2424
use Devscast\Lugha\Provider\Service\Client;
2525
use Devscast\Lugha\Provider\Service\HasCompletionSupport;
26-
use Devscast\Lugha\Provider\Service\HasEmbeddingSupport;
26+
use Devscast\Lugha\Provider\Service\HasEmbeddingsSupport;
2727

2828
/**
2929
* Class GoogleClient.
@@ -33,14 +33,14 @@
3333
*
3434
* @author bernard-ng <bernard@devscast.tech>
3535
*/
36-
final class GoogleClient extends Client implements HasEmbeddingSupport, HasCompletionSupport
36+
final class GoogleClient extends Client implements HasEmbeddingsSupport, HasCompletionSupport
3737
{
3838
protected const string BASE_URI = 'https://generativelanguage.googleapis.com/v1beta/';
3939

4040
protected Provider $provider = Provider::GOOGLE;
4141

4242
#[\Override]
43-
public function embeddings(string $prompt, EmbeddingsConfig $config): EmbeddingResponse
43+
public function embeddings(string $prompt, EmbeddingsConfig $config): EmbeddingsResponse
4444
{
4545
Assert::notEmpty($prompt);
4646

@@ -58,10 +58,10 @@ public function embeddings(string $prompt, EmbeddingsConfig $config): EmbeddingR
5858
],
5959
])->toArray();
6060

61-
return new EmbeddingResponse(
61+
return new EmbeddingsResponse(
6262
provider: $this->provider,
6363
model: $config->model,
64-
embedding: $response['embedding']['values'],
64+
embeddings: $response['embedding']['values'],
6565
providerResponse: $this->config->providerResponse ? $response : [],
6666
);
6767
} catch (\Throwable $e) {

src/Provider/Service/Client/MistralClient.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@
2020
use Devscast\Lugha\Model\Embeddings\EmbeddingsConfig;
2121
use Devscast\Lugha\Provider\Provider;
2222
use Devscast\Lugha\Provider\Response\CompletionResponse;
23-
use Devscast\Lugha\Provider\Response\EmbeddingResponse;
23+
use Devscast\Lugha\Provider\Response\EmbeddingsResponse;
2424
use Devscast\Lugha\Provider\Service\Client;
2525
use Devscast\Lugha\Provider\Service\Common\OpenAICompatibilitySupport;
2626
use Devscast\Lugha\Provider\Service\Common\ToolCallingSupport;
2727
use Devscast\Lugha\Provider\Service\HasCompletionSupport;
28-
use Devscast\Lugha\Provider\Service\HasEmbeddingSupport;
28+
use Devscast\Lugha\Provider\Service\HasEmbeddingsSupport;
2929

3030
/**
3131
* Class MistralClient.
@@ -35,7 +35,7 @@
3535
*
3636
* @author bernard-ng <bernard@devscast.tech>
3737
*/
38-
final class MistralClient extends Client implements HasEmbeddingSupport, HasCompletionSupport
38+
final class MistralClient extends Client implements HasEmbeddingsSupport, HasCompletionSupport
3939
{
4040
use ToolCallingSupport;
4141
use OpenAICompatibilitySupport;
@@ -45,7 +45,7 @@ final class MistralClient extends Client implements HasEmbeddingSupport, HasComp
4545
protected Provider $provider = Provider::MISTRAL;
4646

4747
#[\Override]
48-
public function embeddings(string $prompt, EmbeddingsConfig $config): EmbeddingResponse
48+
public function embeddings(string $prompt, EmbeddingsConfig $config): EmbeddingsResponse
4949
{
5050
Assert::notEmpty($prompt);
5151

@@ -59,10 +59,10 @@ public function embeddings(string $prompt, EmbeddingsConfig $config): EmbeddingR
5959
],
6060
])->toArray();
6161

62-
return new EmbeddingResponse(
62+
return new EmbeddingsResponse(
6363
provider: $this->provider,
6464
model: $config->model,
65-
embedding: $response['data'][0]['embedding'],
65+
embeddings: $response['data'][0]['embedding'],
6666
providerResponse: $this->config->providerResponse ? $response : [],
6767
);
6868
} catch (\Throwable $e) {

src/Provider/Service/Client/OllamaClient.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@
2020
use Devscast\Lugha\Model\Embeddings\EmbeddingsConfig;
2121
use Devscast\Lugha\Provider\Provider;
2222
use Devscast\Lugha\Provider\Response\CompletionResponse;
23-
use Devscast\Lugha\Provider\Response\EmbeddingResponse;
23+
use Devscast\Lugha\Provider\Response\EmbeddingsResponse;
2424
use Devscast\Lugha\Provider\Service\Client;
2525
use Devscast\Lugha\Provider\Service\Common\OpenAICompatibilitySupport;
2626
use Devscast\Lugha\Provider\Service\Common\ToolCallingSupport;
2727
use Devscast\Lugha\Provider\Service\HasCompletionSupport;
28-
use Devscast\Lugha\Provider\Service\HasEmbeddingSupport;
28+
use Devscast\Lugha\Provider\Service\HasEmbeddingsSupport;
2929

3030
/**
3131
* Class OllamaClient.
@@ -34,7 +34,7 @@
3434
*
3535
* @author bernard-ng <bernard@devscast.tech>
3636
*/
37-
final class OllamaClient extends Client implements HasEmbeddingSupport, HasCompletionSupport
37+
final class OllamaClient extends Client implements HasEmbeddingsSupport, HasCompletionSupport
3838
{
3939
use ToolCallingSupport;
4040
use OpenAICompatibilitySupport;
@@ -44,7 +44,7 @@ final class OllamaClient extends Client implements HasEmbeddingSupport, HasCompl
4444
protected Provider $provider = Provider::OLLAMA;
4545

4646
#[\Override]
47-
public function embeddings(string $prompt, EmbeddingsConfig $config): EmbeddingResponse
47+
public function embeddings(string $prompt, EmbeddingsConfig $config): EmbeddingsResponse
4848
{
4949
Assert::notEmpty($prompt);
5050

@@ -58,10 +58,10 @@ public function embeddings(string $prompt, EmbeddingsConfig $config): EmbeddingR
5858
],
5959
])->toArray();
6060

61-
return new EmbeddingResponse(
61+
return new EmbeddingsResponse(
6262
provider: $this->provider,
6363
model: $config->model,
64-
embedding: $response['embedding']
64+
embeddings: $response['embedding']
6565
);
6666
} catch (\Throwable $e) {
6767
throw new ServiceIntegrationException('Unable to generate embeddings.', previous: $e);

src/Provider/Service/Client/OpenAIClient.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@
2020
use Devscast\Lugha\Model\Embeddings\EmbeddingsConfig;
2121
use Devscast\Lugha\Provider\Provider;
2222
use Devscast\Lugha\Provider\Response\CompletionResponse;
23-
use Devscast\Lugha\Provider\Response\EmbeddingResponse;
23+
use Devscast\Lugha\Provider\Response\EmbeddingsResponse;
2424
use Devscast\Lugha\Provider\Service\Client;
2525
use Devscast\Lugha\Provider\Service\Common\OpenAICompatibilitySupport;
2626
use Devscast\Lugha\Provider\Service\Common\ToolCallingSupport;
2727
use Devscast\Lugha\Provider\Service\HasCompletionSupport;
28-
use Devscast\Lugha\Provider\Service\HasEmbeddingSupport;
28+
use Devscast\Lugha\Provider\Service\HasEmbeddingsSupport;
2929

3030
/**
3131
* Class OpenAIClient.
@@ -37,7 +37,7 @@
3737
*
3838
* @author bernard-ng <bernard@devscast.tech>
3939
*/
40-
final class OpenAIClient extends Client implements HasEmbeddingSupport, HasCompletionSupport
40+
final class OpenAIClient extends Client implements HasEmbeddingsSupport, HasCompletionSupport
4141
{
4242
use ToolCallingSupport;
4343
use OpenAICompatibilitySupport;
@@ -47,7 +47,7 @@ final class OpenAIClient extends Client implements HasEmbeddingSupport, HasCompl
4747
protected Provider $provider = Provider::OPENAI;
4848

4949
#[\Override]
50-
public function embeddings(string $prompt, EmbeddingsConfig $config): EmbeddingResponse
50+
public function embeddings(string $prompt, EmbeddingsConfig $config): EmbeddingsResponse
5151
{
5252
Assert::notEmpty($prompt);
5353

@@ -62,10 +62,10 @@ public function embeddings(string $prompt, EmbeddingsConfig $config): EmbeddingR
6262
],
6363
])->toArray();
6464

65-
return new EmbeddingResponse(
65+
return new EmbeddingsResponse(
6666
provider: $this->provider,
6767
model: $config->model,
68-
embedding: $response['data'][0]['embedding'],
68+
embeddings: $response['data'][0]['embedding'],
6969
providerResponse: $this->config->providerResponse ? $response : [],
7070
);
7171
} catch (\Throwable $e) {

0 commit comments

Comments
 (0)