diff --git a/docs/cookbook/rag-implementation.rst b/docs/cookbook/rag-implementation.rst index d406dbcde..982f5f64a 100644 --- a/docs/cookbook/rag-implementation.rst +++ b/docs/cookbook/rag-implementation.rst @@ -203,7 +203,7 @@ Document Loading Strategies $articles = $articleRepository->findAll(); $documents = array_map( fn($article) => new TextDocument( - id: Uuid::fromString($article->getId()), + id: $article->getId(), content: $article->getTitle().PHP_EOL.$article->getContent(), metadata: new Metadata(['author' => $article->getAuthor()]) ), diff --git a/src/store/src/Bridge/AzureSearch/SearchStore.php b/src/store/src/Bridge/AzureSearch/SearchStore.php index 77c28745e..d7640a002 100644 --- a/src/store/src/Bridge/AzureSearch/SearchStore.php +++ b/src/store/src/Bridge/AzureSearch/SearchStore.php @@ -16,7 +16,6 @@ use Symfony\AI\Store\Document\Metadata; use Symfony\AI\Store\Document\VectorDocument; use Symfony\AI\Store\StoreInterface; -use Symfony\Component\Uid\Uuid; use Symfony\Contracts\HttpClient\HttpClientInterface; /** @@ -91,7 +90,7 @@ private function convertToIndexableArray(VectorDocument $document): array private function convertToVectorDocument(array $data): VectorDocument { return new VectorDocument( - id: Uuid::fromString($data['id']), + id: $data['id'], vector: !\array_key_exists($this->vectorFieldName, $data) || null === $data[$this->vectorFieldName] ? new NullVector() : new Vector($data[$this->vectorFieldName]), diff --git a/src/store/src/Bridge/Cache/Store.php b/src/store/src/Bridge/Cache/Store.php index ce6e12a99..f9cc46610 100644 --- a/src/store/src/Bridge/Cache/Store.php +++ b/src/store/src/Bridge/Cache/Store.php @@ -19,7 +19,6 @@ use Symfony\AI\Store\Exception\InvalidArgumentException; use Symfony\AI\Store\ManagedStoreInterface; use Symfony\AI\Store\StoreInterface; -use Symfony\Component\Uid\Uuid; use Symfony\Contracts\Cache\CacheInterface; /** @@ -79,7 +78,7 @@ public function query(Vector $vector, array $options = []): iterable $documents = $this->cache->get($this->cacheKey, static fn (): array => []); $vectorDocuments = array_map(static fn (array $document): VectorDocument => new VectorDocument( - id: Uuid::fromString($document['id']), + id: $document['id'], vector: new Vector($document['vector']), metadata: new Metadata($document['metadata']), ), $documents); diff --git a/src/store/src/Bridge/ChromaDb/Store.php b/src/store/src/Bridge/ChromaDb/Store.php index 5a9b17934..2e6cdda9b 100644 --- a/src/store/src/Bridge/ChromaDb/Store.php +++ b/src/store/src/Bridge/ChromaDb/Store.php @@ -16,7 +16,6 @@ use Symfony\AI\Store\Document\Metadata; use Symfony\AI\Store\Document\VectorDocument; use Symfony\AI\Store\StoreInterface; -use Symfony\Component\Uid\Uuid; /** * @author Christopher Hertel @@ -83,7 +82,7 @@ public function query(Vector $vector, array $options = []): iterable } yield new VectorDocument( - id: Uuid::fromString($queryResponse->ids[0][$i]), + id: $queryResponse->ids[0][$i], vector: new Vector($queryResponse->embeddings[0][$i]), metadata: $metaData, score: $queryResponse->distances[0][$i] ?? null, diff --git a/src/store/src/Bridge/ClickHouse/Store.php b/src/store/src/Bridge/ClickHouse/Store.php index 1b5a06623..d4e0fab1e 100644 --- a/src/store/src/Bridge/ClickHouse/Store.php +++ b/src/store/src/Bridge/ClickHouse/Store.php @@ -18,7 +18,6 @@ use Symfony\AI\Store\Exception\RuntimeException; use Symfony\AI\Store\ManagedStoreInterface; use Symfony\AI\Store\StoreInterface; -use Symfony\Component\Uid\Uuid; use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Contracts\HttpClient\ResponseInterface; @@ -95,7 +94,7 @@ public function query(Vector $vector, array $options = [], ?float $minScore = nu foreach ($results as $result) { yield new VectorDocument( - id: Uuid::fromString($result['id']), + id: $result['id'], vector: new Vector($result['embedding']), metadata: new Metadata(json_decode($result['metadata'] ?? '{}', true, 512, \JSON_THROW_ON_ERROR)), score: $result['score'], diff --git a/src/store/src/Bridge/Cloudflare/Store.php b/src/store/src/Bridge/Cloudflare/Store.php index 446c161ba..6758739c1 100644 --- a/src/store/src/Bridge/Cloudflare/Store.php +++ b/src/store/src/Bridge/Cloudflare/Store.php @@ -18,7 +18,6 @@ use Symfony\AI\Store\Exception\InvalidArgumentException; use Symfony\AI\Store\ManagedStoreInterface; use Symfony\AI\Store\StoreInterface; -use Symfony\Component\Uid\Uuid; use Symfony\Contracts\HttpClient\HttpClientInterface; /** @@ -138,7 +137,7 @@ private function convertToVectorDocument(array $data): VectorDocument : new Vector($data['values']); return new VectorDocument( - id: Uuid::fromString($id), + id: $id, vector: $vector, metadata: new Metadata($data['metadata']), score: $data['score'] ?? null diff --git a/src/store/src/Bridge/ManticoreSearch/Store.php b/src/store/src/Bridge/ManticoreSearch/Store.php index 1583d6e4f..53a5548a5 100644 --- a/src/store/src/Bridge/ManticoreSearch/Store.php +++ b/src/store/src/Bridge/ManticoreSearch/Store.php @@ -18,7 +18,6 @@ use Symfony\AI\Store\Exception\InvalidArgumentException; use Symfony\AI\Store\ManagedStoreInterface; use Symfony\AI\Store\StoreInterface; -use Symfony\Component\Uid\Uuid; use Symfony\Contracts\HttpClient\HttpClientInterface; /** @@ -150,7 +149,7 @@ private function convertToVectorDocument(array $data): VectorDocument : new Vector($payload[$this->field]); return new VectorDocument( - id: Uuid::fromString($payload['uuid']), + id: $payload['uuid'], vector: $vector, metadata: new Metadata($payload['metadata'] ?? []), score: $data['_knn_dist'] ?? null diff --git a/src/store/src/Bridge/Meilisearch/Store.php b/src/store/src/Bridge/Meilisearch/Store.php index 6f59c7e81..dfcbd98c2 100644 --- a/src/store/src/Bridge/Meilisearch/Store.php +++ b/src/store/src/Bridge/Meilisearch/Store.php @@ -130,7 +130,7 @@ private function request(string $method, string $endpoint, array $payload): arra private function convertToIndexableArray(VectorDocument $document): array { return array_merge([ - 'id' => $document->id->toRfc4122(), + 'id' => $document->id, $this->vectorFieldName => [ $this->embedder => [ 'embeddings' => $document->vector->getData(), @@ -154,6 +154,6 @@ private function convertToVectorDocument(array $data): VectorDocument unset($data['id'], $data[$this->vectorFieldName], $data['_rankingScore']); - return new VectorDocument(Uuid::fromString($id), $vector, new Metadata($data), $score); + return new VectorDocument($id, $vector, new Metadata($data), $score); } } diff --git a/src/store/src/Bridge/Milvus/Store.php b/src/store/src/Bridge/Milvus/Store.php index 13dc16bc9..33e5ec681 100644 --- a/src/store/src/Bridge/Milvus/Store.php +++ b/src/store/src/Bridge/Milvus/Store.php @@ -151,7 +151,7 @@ private function request(string $method, string $endpoint, array $payload): arra private function convertToIndexableArray(VectorDocument $document): array { return [ - 'id' => $document->id->toRfc4122(), + 'id' => $document->id, '_metadata' => json_encode($document->metadata->getArrayCopy()), $this->vectorFieldName => $document->vector->getData(), ]; @@ -170,6 +170,6 @@ private function convertToVectorDocument(array $data): VectorDocument $score = $data['distance'] ?? null; - return new VectorDocument(Uuid::fromString($id), $vector, new Metadata(json_decode($data['_metadata'], true)), $score); + return new VectorDocument($id, $vector, new Metadata(json_decode($data['_metadata'], true)), $score); } } diff --git a/src/store/src/Bridge/MongoDb/Store.php b/src/store/src/Bridge/MongoDb/Store.php index 09d1c0b46..14bb0670e 100644 --- a/src/store/src/Bridge/MongoDb/Store.php +++ b/src/store/src/Bridge/MongoDb/Store.php @@ -179,7 +179,7 @@ public function query(Vector $vector, array $options = []): iterable foreach ($results as $result) { yield new VectorDocument( - id: $this->toUuid($result['_id']), + id: $this->getBinaryData($result['_id']), vector: new Vector($result[$this->vectorFieldName]), metadata: new Metadata($result['metadata'] ?? []), score: $result['score'], @@ -197,8 +197,8 @@ private function toBinary(Uuid $uuid): Binary return new Binary($uuid->toBinary(), Binary::TYPE_UUID); } - private function toUuid(Binary $binary): Uuid + private function getBinaryData(Binary $binary): string { - return Uuid::fromString($binary->getData()); + return $binary->getData(); } } diff --git a/src/store/src/Bridge/Neo4j/Store.php b/src/store/src/Bridge/Neo4j/Store.php index 1662ddee2..e66013d80 100644 --- a/src/store/src/Bridge/Neo4j/Store.php +++ b/src/store/src/Bridge/Neo4j/Store.php @@ -18,7 +18,6 @@ use Symfony\AI\Store\Exception\InvalidArgumentException; use Symfony\AI\Store\ManagedStoreInterface; use Symfony\AI\Store\StoreInterface; -use Symfony\Component\Uid\Uuid; use Symfony\Contracts\HttpClient\HttpClientInterface; /** @@ -117,7 +116,7 @@ private function convertToVectorDocument(array $data): VectorDocument : new Vector($payload['properties'][$this->embeddingsField]); return new VectorDocument( - id: Uuid::fromString($id), + id: $id, vector: $vector, metadata: new Metadata(json_decode($payload['properties']['metadata'], true)), score: $data[1] ?? null diff --git a/src/store/src/Bridge/OpenSearch/Store.php b/src/store/src/Bridge/OpenSearch/Store.php index 4fc658e8b..2b9e5aaa1 100644 --- a/src/store/src/Bridge/OpenSearch/Store.php +++ b/src/store/src/Bridge/OpenSearch/Store.php @@ -76,7 +76,7 @@ public function add(VectorDocument ...$documents): void $documentToIndex = fn (VectorDocument $document): array => [ 'index' => [ '_index' => $this->indexName, - '_id' => $document->id->toRfc4122(), + '_id' => $document->id, ], ]; @@ -153,6 +153,6 @@ private function convertToVectorDocument(array $document): VectorDocument ? new NullVector() : new Vector($document['_source'][$this->vectorsField]); - return new VectorDocument(Uuid::fromString($id), $vector, new Metadata(json_decode($document['_source']['metadata'], true)), $document['_score'] ?? null); + return new VectorDocument($id, $vector, new Metadata(json_decode($document['_source']['metadata'], true)), $document['_score'] ?? null); } } diff --git a/src/store/src/Bridge/Pinecone/Store.php b/src/store/src/Bridge/Pinecone/Store.php index deabd8bbb..77b19bdc2 100644 --- a/src/store/src/Bridge/Pinecone/Store.php +++ b/src/store/src/Bridge/Pinecone/Store.php @@ -17,7 +17,6 @@ use Symfony\AI\Store\Document\Metadata; use Symfony\AI\Store\Document\VectorDocument; use Symfony\AI\Store\StoreInterface; -use Symfony\Component\Uid\Uuid; /** * @author Christopher Hertel @@ -65,7 +64,7 @@ public function query(Vector $vector, array $options = []): iterable foreach ($result->json()['matches'] as $match) { yield new VectorDocument( - id: Uuid::fromString($match['id']), + id: $match['id'], vector: new Vector($match['values']), metadata: new Metadata($match['metadata']), score: $match['score'], diff --git a/src/store/src/Bridge/Postgres/Store.php b/src/store/src/Bridge/Postgres/Store.php index 9294ca2ac..26b1fce79 100644 --- a/src/store/src/Bridge/Postgres/Store.php +++ b/src/store/src/Bridge/Postgres/Store.php @@ -19,7 +19,6 @@ use Symfony\AI\Store\Exception\InvalidArgumentException; use Symfony\AI\Store\ManagedStoreInterface; use Symfony\AI\Store\StoreInterface; -use Symfony\Component\Uid\Uuid; /** * Requires PostgreSQL with pgvector extension. @@ -172,7 +171,7 @@ public function query(Vector $vector, array $options = []): iterable foreach ($statement->fetchAll(\PDO::FETCH_ASSOC) as $result) { yield new VectorDocument( - id: Uuid::fromString($result['id']), + id: $result['id'], vector: new Vector($this->fromPgvector($result['embedding'])), metadata: new Metadata(json_decode($result['metadata'] ?? '{}', true, 512, \JSON_THROW_ON_ERROR)), score: $result['score'], diff --git a/src/store/src/Bridge/Qdrant/Store.php b/src/store/src/Bridge/Qdrant/Store.php index 6d6e4bbbb..f915f8c7f 100644 --- a/src/store/src/Bridge/Qdrant/Store.php +++ b/src/store/src/Bridge/Qdrant/Store.php @@ -18,7 +18,6 @@ use Symfony\AI\Store\Exception\InvalidArgumentException; use Symfony\AI\Store\ManagedStoreInterface; use Symfony\AI\Store\StoreInterface; -use Symfony\Component\Uid\Uuid; use Symfony\Contracts\HttpClient\HttpClientInterface; /** @@ -153,7 +152,7 @@ private function convertToVectorDocument(array $data): VectorDocument : new Vector($data['vector']); return new VectorDocument( - id: Uuid::fromString($id), + id: $id, vector: $vector, metadata: new Metadata($data['payload']), score: $data['score'] ?? null diff --git a/src/store/src/Bridge/Redis/Store.php b/src/store/src/Bridge/Redis/Store.php index 85b43aa8e..ecbfe255c 100644 --- a/src/store/src/Bridge/Redis/Store.php +++ b/src/store/src/Bridge/Redis/Store.php @@ -18,7 +18,6 @@ use Symfony\AI\Store\Exception\RuntimeException; use Symfony\AI\Store\ManagedStoreInterface; use Symfony\AI\Store\StoreInterface; -use Symfony\Component\Uid\Uuid; /** * @author Grégoire Pineau @@ -167,7 +166,7 @@ public function query(Vector $vector, array $options = []): iterable } yield new VectorDocument( - id: Uuid::fromString($data['$.id']), + id: $data['$.id'], vector: new Vector($data['$.embedding'] ?? []), metadata: new Metadata($data['$.metadata'] ?? []), score: $score, diff --git a/src/store/src/Bridge/Supabase/Store.php b/src/store/src/Bridge/Supabase/Store.php index d72ec5dc4..aae3348e6 100644 --- a/src/store/src/Bridge/Supabase/Store.php +++ b/src/store/src/Bridge/Supabase/Store.php @@ -17,7 +17,6 @@ use Symfony\AI\Store\Exception\InvalidArgumentException; use Symfony\AI\Store\Exception\RuntimeException; use Symfony\AI\Store\StoreInterface; -use Symfony\Component\Uid\Uuid; use Symfony\Contracts\HttpClient\HttpClientInterface; /** @@ -137,7 +136,7 @@ public function query(Vector $vector, array $options = []): iterable $metadata = \is_array($record['metadata']) ? $record['metadata'] : json_decode($record['metadata'], true, 512, \JSON_THROW_ON_ERROR); yield new VectorDocument( - id: Uuid::fromString($record['id']), + id: $record['id'], vector: new Vector($embedding), metadata: new Metadata($metadata), score: (float) $record['score'], diff --git a/src/store/src/Bridge/Supabase/Tests/StoreTest.php b/src/store/src/Bridge/Supabase/Tests/StoreTest.php index f353e0394..c99873fc2 100644 --- a/src/store/src/Bridge/Supabase/Tests/StoreTest.php +++ b/src/store/src/Bridge/Supabase/Tests/StoreTest.php @@ -144,7 +144,7 @@ public function testQuerySuccess() $this->assertCount(1, $result); $this->assertInstanceOf(VectorDocument::class, $result[0]); - $this->assertTrue($uuid->equals($result[0]->id)); + $this->assertSame($uuid->toRfc4122(), $result[0]->id); $this->assertSame([0.5, 0.6, 0.7], $result[0]->vector->getData()); $this->assertSame(['category' => 'test'], $result[0]->metadata->getArrayCopy()); $this->assertSame(0.85, $result[0]->score); @@ -176,12 +176,12 @@ public function testQueryHandlesMultipleResultsAndMultipleOptions() $this->assertCount(2, $result); $this->assertInstanceOf(VectorDocument::class, $result[0]); - $this->assertTrue($uuid1->equals($result[0]->id)); + $this->assertSame($uuid1->toRfc4122(), $result[0]->id); $this->assertSame([0.1, 0.2], $result[0]->vector->getData()); $this->assertSame(0.95, $result[0]->score); $this->assertSame(['type' => 'first'], $result[0]->metadata->getArrayCopy()); $this->assertInstanceOf(VectorDocument::class, $result[1]); - $this->assertTrue($uuid2->equals($result[1]->id)); + $this->assertSame($uuid2->toRfc4122(), $result[1]->id); $this->assertSame([0.3, 0.4], $result[1]->vector->getData()); $this->assertSame(0.85, $result[1]->score); $this->assertSame(['type' => 'second'], $result[1]->metadata->getArrayCopy()); @@ -209,7 +209,7 @@ public function testQueryParsesComplexMetadata() $metadata = $document->metadata->getArrayCopy(); $this->assertCount(1, $result); $this->assertInstanceOf(VectorDocument::class, $document); - $this->assertTrue($uuid->equals($document->id)); + $this->assertSame($uuid->toRfc4122(), $document->id); $this->assertSame([0.1, 0.2, 0.3, 0.4], $document->vector->getData()); $this->assertSame(0.92, $document->score); $this->assertSame('Test Document', $metadata['title']); diff --git a/src/store/src/Bridge/SurrealDb/Store.php b/src/store/src/Bridge/SurrealDb/Store.php index 8c5da67c6..b8a22dfeb 100644 --- a/src/store/src/Bridge/SurrealDb/Store.php +++ b/src/store/src/Bridge/SurrealDb/Store.php @@ -19,7 +19,6 @@ use Symfony\AI\Store\Exception\RuntimeException; use Symfony\AI\Store\ManagedStoreInterface; use Symfony\AI\Store\StoreInterface; -use Symfony\Component\Uid\Uuid; use Symfony\Contracts\HttpClient\HttpClientInterface; /** @@ -149,7 +148,7 @@ private function convertToVectorDocument(array $data): VectorDocument unset($data['_metadata']['_id']); return new VectorDocument( - id: Uuid::fromString($id), + id: $id, vector: $vector, metadata: new Metadata($data['_metadata']), ); diff --git a/src/store/src/Bridge/Typesense/Store.php b/src/store/src/Bridge/Typesense/Store.php index f501ef99b..d9066eab9 100644 --- a/src/store/src/Bridge/Typesense/Store.php +++ b/src/store/src/Bridge/Typesense/Store.php @@ -115,7 +115,7 @@ private function request(string $method, string $endpoint, array $payload): arra private function convertToIndexableArray(VectorDocument $document): array { return [ - 'id' => $document->id->toRfc4122(), + 'id' => $document->id, $this->vectorFieldName => $document->vector->getData(), 'metadata' => json_encode($document->metadata->getArrayCopy()), ]; @@ -136,6 +136,6 @@ private function convertToVectorDocument(array $data): VectorDocument $score = $data['vector_distance'] ?? null; - return new VectorDocument(Uuid::fromString($id), $vector, new Metadata(json_decode($document['metadata'], true)), $score); + return new VectorDocument($id, $vector, new Metadata(json_decode($document['metadata'], true)), $score); } } diff --git a/src/store/src/Bridge/Weaviate/Store.php b/src/store/src/Bridge/Weaviate/Store.php index 07efcccd2..ad873aa18 100644 --- a/src/store/src/Bridge/Weaviate/Store.php +++ b/src/store/src/Bridge/Weaviate/Store.php @@ -116,10 +116,10 @@ private function convertToIndexableArray(VectorDocument $document): array { return [ 'class' => $this->collection, - 'id' => $document->id->toRfc4122(), + 'id' => $document->id, 'vector' => $document->vector->getData(), 'properties' => [ - 'uuid' => $document->id->toRfc4122(), + 'uuid' => $document->id, 'vector' => $document->vector->getData(), '_metadata' => json_encode($document->metadata->getArrayCopy()), ], @@ -137,6 +137,6 @@ private function convertToVectorDocument(array $data): VectorDocument ? new NullVector() : new Vector($data['vector']); - return new VectorDocument(Uuid::fromString($id), $vector, new Metadata(json_decode($data['_metadata'], true))); + return new VectorDocument($id, $vector, new Metadata(json_decode($data['_metadata'], true))); } } diff --git a/src/store/src/Document/TextDocument.php b/src/store/src/Document/TextDocument.php index eefac3f31..cd3b5da54 100644 --- a/src/store/src/Document/TextDocument.php +++ b/src/store/src/Document/TextDocument.php @@ -20,7 +20,7 @@ final class TextDocument implements EmbeddableDocumentInterface { public function __construct( - private readonly Uuid $id, + private readonly int|string|Uuid $id, private readonly string $content, private readonly Metadata $metadata = new Metadata(), ) { @@ -34,7 +34,7 @@ public function withContent(string $content): self return new self($this->id, $content, $this->metadata); } - public function getId(): Uuid + public function getId(): int|string|Uuid { return $this->id; } diff --git a/src/store/src/Document/VectorDocument.php b/src/store/src/Document/VectorDocument.php index 861f0d882..b076ae34d 100644 --- a/src/store/src/Document/VectorDocument.php +++ b/src/store/src/Document/VectorDocument.php @@ -20,7 +20,7 @@ final class VectorDocument { public function __construct( - public readonly Uuid $id, + public readonly int|string|Uuid $id, public readonly VectorInterface $vector, public readonly Metadata $metadata = new Metadata(), public readonly ?float $score = null, diff --git a/src/store/tests/Document/TextDocumentTest.php b/src/store/tests/Document/TextDocumentTest.php index 5f9c876ad..0a36eaad5 100644 --- a/src/store/tests/Document/TextDocumentTest.php +++ b/src/store/tests/Document/TextDocumentTest.php @@ -22,6 +22,20 @@ final class TextDocumentTest extends TestCase { + #[TestWith([1])] + #[TestWith(['id'])] + #[TestWith(['uuid'])] + public function testConstructorIdSupportsManyTypes(int|string $id) + { + if ('uuid' === $id) { + $id = Uuid::v4(); + } + + $document = new TextDocument($id, 'content'); + + $this->assertSame($id, $document->getId()); + } + #[TestDox('Creates document with valid content and metadata')] public function testConstructorWithValidContent() { diff --git a/src/store/tests/Document/VectorDocumentTest.php b/src/store/tests/Document/VectorDocumentTest.php index 54a5c2f82..2b94a5c9b 100644 --- a/src/store/tests/Document/VectorDocumentTest.php +++ b/src/store/tests/Document/VectorDocumentTest.php @@ -15,6 +15,7 @@ use PHPUnit\Framework\Attributes\TestDox; use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\TestCase; +use Symfony\AI\Platform\Vector\NullVector; use Symfony\AI\Platform\Vector\Vector; use Symfony\AI\Store\Document\Metadata; use Symfony\AI\Store\Document\VectorDocument; @@ -25,6 +26,20 @@ */ final class VectorDocumentTest extends TestCase { + #[TestWith([1])] + #[TestWith(['id'])] + #[TestWith(['uuid'])] + public function testConstructorIdSupportsManyTypes(int|string $id) + { + if ('uuid' === $id) { + $id = Uuid::v4(); + } + + $document = new VectorDocument($id, new NullVector()); + + $this->assertSame($id, $document->id); + } + #[TestDox('Creates document with required parameters only')] public function testConstructorWithRequiredParameters() {