Skip to content

Commit ec118a0

Browse files
authored
feat: add pinecone store (#55)
1 parent 2e8f434 commit ec118a0

File tree

5 files changed

+85
-4
lines changed

5 files changed

+85
-4
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Supported Stores
4646
* [x] [ChromaDB](https://trychroma.com)
4747
* [x] [Azure AI Search](https://azure.microsoft.com/en-us/products/ai-services/ai-search)
4848
* [x] [MongoDB Atlas Search](https://mongodb.com/products/platform/atlas-vector-search)
49-
* [ ] [Pinecone](https://pinecone.io)
49+
* [x] [Pinecone](https://pinecone.io)
5050

5151
Provided Tools
5252
--------------

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@
3838
"symfony/var-dumper": "^6.4 || ^7.1"
3939
},
4040
"suggest": {
41-
"mongodb/mongodb": "For using MongoDB Atlas as retrieval vector store.",
4241
"codewithkyrian/chromadb-php": "For using the ChromaDB as retrieval vector store.",
42+
"mongodb/mongodb": "For using MongoDB Atlas as retrieval vector store.",
43+
"probots-io/pinecone-php": "For using the Pinecone as retrieval vector store.",
4344
"symfony/clock": "For using the clock tool.",
4445
"symfony/css-selector": "For using the YouTube transcription tool.",
4546
"symfony/dom-crawler": "For using the YouTube transcription tool."

src/Document/Vector.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ final class Vector
99
/**
1010
* @param list<float> $data
1111
*/
12-
private function __construct(
12+
public function __construct(
1313
private readonly array $data,
1414
private ?int $dimensions = null,
1515
) {

src/Store/MongoDB/Store.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ public function query(Vector $vector, array $options = []): array
126126

127127
foreach ($results as $result) {
128128
$documents[] = Document::fromVector(
129-
Vector::create1536($result[$this->vectorFieldName]),
129+
new Vector($result[$this->vectorFieldName]),
130130
$this->toUuid($result['_id']),
131131
new Metadata($result['metadata'] ?? []),
132132
);

src/Store/Pinecone/Store.php

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpLlm\LlmChain\Store\Pinecone;
6+
7+
use PhpLlm\LlmChain\Document\Document;
8+
use PhpLlm\LlmChain\Document\Metadata;
9+
use PhpLlm\LlmChain\Document\Vector;
10+
use PhpLlm\LlmChain\Store\VectorStoreInterface;
11+
use Probots\Pinecone\Client;
12+
use Probots\Pinecone\Resources\Data\VectorResource;
13+
use Psr\Log\LoggerInterface;
14+
use Symfony\Component\Uid\Uuid;
15+
16+
final readonly class Store implements VectorStoreInterface
17+
{
18+
/**
19+
* @param array<string, mixed> $filter
20+
*/
21+
public function __construct(
22+
private Client $pinecone,
23+
private LoggerInterface $logger,
24+
private ?string $namespace = null,
25+
private array $filter = [],
26+
private int $topK = 3,
27+
) {
28+
}
29+
30+
public function addDocument(Document $document): void
31+
{
32+
$this->addDocuments([$document]);
33+
}
34+
35+
public function addDocuments(array $documents): void
36+
{
37+
$vectors = [];
38+
foreach ($documents as $document) {
39+
if (!$document->hasVector()) {
40+
$this->logger->warning('Document {id} does not have a vector', ['id' => $document->id]);
41+
continue;
42+
}
43+
44+
$vectors[] = [
45+
'id' => (string) $document->id,
46+
'values' => $document->vector->getData(),
47+
'metadata' => $document->metadata->getArrayCopy(),
48+
];
49+
}
50+
51+
$this->getVectors()->upsert($vectors);
52+
}
53+
54+
public function query(Vector $vector, array $options = []): array
55+
{
56+
$response = $this->getVectors()->query(
57+
vector: $vector->getData(),
58+
namespace: $options['namespace'] ?? $this->namespace,
59+
filter: $options['filter'] ?? $this->filter,
60+
topK: $options['topK'] ?? $this->topK,
61+
includeValues: true,
62+
);
63+
64+
$documents = [];
65+
foreach ($response->json()['matches'] as $match) {
66+
$documents[] = Document::fromVector(
67+
new Vector($match['values']),
68+
Uuid::fromString($match['id']),
69+
new Metadata($match['metadata']),
70+
);
71+
}
72+
73+
return $documents;
74+
}
75+
76+
private function getVectors(): VectorResource
77+
{
78+
return $this->pinecone->data()->vectors();
79+
}
80+
}

0 commit comments

Comments
 (0)