diff --git a/docs/cookbook/rag-implementation.rst b/docs/cookbook/rag-implementation.rst index cdccb395b..043562436 100644 --- a/docs/cookbook/rag-implementation.rst +++ b/docs/cookbook/rag-implementation.rst @@ -205,7 +205,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/Azure/SearchStore.php b/src/store/src/Bridge/Azure/SearchStore.php index 6e6dc5fed..a581b7e2a 100644 --- a/src/store/src/Bridge/Azure/SearchStore.php +++ b/src/store/src/Bridge/Azure/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; /** @@ -89,7 +88,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/ChromaDb/Store.php b/src/store/src/Bridge/ChromaDb/Store.php index 3f29f44e6..467efa3db 100644 --- a/src/store/src/Bridge/ChromaDb/Store.php +++ b/src/store/src/Bridge/ChromaDb/Store.php @@ -17,7 +17,6 @@ use Symfony\AI\Store\Document\VectorDocument; use Symfony\AI\Store\Exception\RuntimeException; use Symfony\AI\Store\StoreInterface; -use Symfony\Component\Uid\Uuid; /** * @author Christopher Hertel @@ -68,7 +67,7 @@ public function query(Vector $vector, array $options = []): array $documents = []; for ($i = 0; $i < \count($queryResponse->metadatas[0]); ++$i) { $documents[] = new VectorDocument( - id: Uuid::fromString($queryResponse->ids[0][$i]), + id: $queryResponse->ids[0][$i], vector: new Vector($queryResponse->embeddings[0][$i]), metadata: new Metadata($queryResponse->metadatas[0][$i]), ); diff --git a/src/store/src/Bridge/ClickHouse/Store.php b/src/store/src/Bridge/ClickHouse/Store.php index 5f4f4b84f..b39bed510 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; @@ -96,7 +95,7 @@ public function query(Vector $vector, array $options = [], ?float $minScore = nu $documents = []; foreach ($results as $result) { $documents[] = 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 f248e15c9..6186ba268 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; /** @@ -136,7 +135,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/Local/CacheStore.php b/src/store/src/Bridge/Local/CacheStore.php index ad85bea40..013fd3fc0 100644 --- a/src/store/src/Bridge/Local/CacheStore.php +++ b/src/store/src/Bridge/Local/CacheStore.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\Cache\CacheInterface; /** @@ -80,7 +79,7 @@ public function query(Vector $vector, array $options = []): array $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/Manticore/Store.php b/src/store/src/Bridge/Manticore/Store.php index f5b9f51ff..eac744fca 100644 --- a/src/store/src/Bridge/Manticore/Store.php +++ b/src/store/src/Bridge/Manticore/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; /** @@ -148,7 +147,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/Neo4j/Store.php b/src/store/src/Bridge/Neo4j/Store.php index a69d2ab92..5c37d6685 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; /** @@ -115,7 +114,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/Pinecone/Store.php b/src/store/src/Bridge/Pinecone/Store.php index ac5a01d22..c3b3e5e8f 100644 --- a/src/store/src/Bridge/Pinecone/Store.php +++ b/src/store/src/Bridge/Pinecone/Store.php @@ -18,7 +18,6 @@ use Symfony\AI\Store\Document\VectorDocument; use Symfony\AI\Store\Exception\RuntimeException; use Symfony\AI\Store\StoreInterface; -use Symfony\Component\Uid\Uuid; /** * @author Christopher Hertel @@ -70,7 +69,7 @@ public function query(Vector $vector, array $options = []): array $documents = []; foreach ($result->json()['matches'] as $match) { $documents[] = 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 cd5ebf1dd..7e2f2e405 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. @@ -173,7 +172,7 @@ public function query(Vector $vector, array $options = []): array $documents = []; foreach ($statement->fetchAll(\PDO::FETCH_ASSOC) as $result) { $documents[] = 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 e0682b39e..83fb70117 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; /** @@ -151,7 +150,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 fd4b6b218..a7f48715b 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 @@ -168,7 +167,7 @@ public function query(Vector $vector, array $options = []): array } $documents[] = 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 8a2d558e7..d9c52efa9 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; /** @@ -138,7 +137,7 @@ public function query(Vector $vector, array $options = []): array $metadata = \is_array($record['metadata']) ? $record['metadata'] : json_decode($record['metadata'], true, 512, \JSON_THROW_ON_ERROR); $documents[] = 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/SurrealDb/Store.php b/src/store/src/Bridge/SurrealDb/Store.php index 5605a91b3..e6865514d 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; /** @@ -147,7 +146,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/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/Bridge/Supabase/StoreTest.php b/src/store/tests/Bridge/Supabase/StoreTest.php index c68627a59..b381481bb 100644 --- a/src/store/tests/Bridge/Supabase/StoreTest.php +++ b/src/store/tests/Bridge/Supabase/StoreTest.php @@ -146,7 +146,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); @@ -178,12 +178,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()); @@ -211,7 +211,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/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() {