Skip to content

Commit

Permalink
V1.9 hybrid search (#649)
Browse files Browse the repository at this point in the history
* Add retrieveVector method to getSimilarDocuments

* Update vector search test checking `_vector` field

* Make document query request the vector

* Rollback compose version

* linter

* Update src/Contracts/DocumentsQuery.php

Co-authored-by: Tomas Norkūnas <norkunas.tom@gmail.com>

---------

Co-authored-by: Tomas Norkūnas <norkunas.tom@gmail.com>
  • Loading branch information
ManyTheFish and norkunas authored Jun 25, 2024
1 parent bbc1116 commit 0b89ce9
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 6 deletions.
14 changes: 13 additions & 1 deletion src/Contracts/DocumentsQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class DocumentsQuery
private int $limit;
private array $fields;
private array $filter;
private ?bool $retrieveVectors = null;

public function setOffset(int $offset): DocumentsQuery
{
Expand Down Expand Up @@ -46,6 +47,16 @@ public function setFilter(array $filter): DocumentsQuery
return $this;
}

/**
* @param bool|null $retrieveVectors boolean value to show _vector details
*/
public function setRetrieveVectors(?bool $retrieveVectors): DocumentsQuery
{
$this->retrieveVectors = $retrieveVectors;

return $this;
}

/**
* Checks if the $filter attribute has been set.
*
Expand Down Expand Up @@ -84,6 +95,7 @@ public function toArray(): array
'limit' => $this->limit ?? null,
'filter' => $this->filter ?? null,
'fields' => $this->fields(),
], function ($item) { return null != $item || is_numeric($item); });
'retrieveVectors' => (null !== $this->retrieveVectors ? ($this->retrieveVectors ? 'true' : 'false') : null),
], function ($item) { return null !== $item; });
}
}
14 changes: 13 additions & 1 deletion src/Contracts/SimilarDocumentsQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class SimilarDocumentsQuery
private ?array $attributesToRetrieve = null;
private ?bool $showRankingScore = null;
private ?bool $showRankingScoreDetails = null;
private ?bool $retrieveVectors = null;
private ?array $filter = null;

/**
Expand Down Expand Up @@ -97,7 +98,17 @@ public function setShowRankingScoreDetails(?bool $showRankingScoreDetails): Simi
}

/**
* @return array{id: int|string, offset: non-negative-int, limit: positive-int, filter: array<int, array<int, string>|string>, embedder: non-empty-string, attributesToRetrieve: list<non-empty-string>, showRankingScore: bool, showRankingScoreDetails: bool} SimilarDocumentsQuery converted to an array with non null fields
* @param bool|null $retrieveVectors boolean value to show _vector details
*/
public function setRetrieveVectors(?bool $retrieveVectors): SimilarDocumentsQuery
{
$this->retrieveVectors = $retrieveVectors;

return $this;
}

/**
* @return array{id: int|string, offset: non-negative-int, limit: positive-int, filter: array<int, array<int, string>|string>, embedder: non-empty-string, attributesToRetrieve: list<non-empty-string>, showRankingScore: bool, showRankingScoreDetails: bool, retrieveVectors: bool} SimilarDocumentsQuery converted to an array with non null fields
*/
public function toArray(): array
{
Expand All @@ -110,6 +121,7 @@ public function toArray(): array
'attributesToRetrieve' => $this->attributesToRetrieve,
'showRankingScore' => $this->showRankingScore,
'showRankingScoreDetails' => $this->showRankingScoreDetails,
'retrieveVectors' => $this->retrieveVectors,
], function ($item) {
return null !== $item;
});
Expand Down
23 changes: 23 additions & 0 deletions tests/Endpoints/DocumentsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Meilisearch\Exceptions\InvalidArgumentException;
use Meilisearch\Exceptions\InvalidResponseBodyException;
use Meilisearch\Exceptions\JsonEncodingException;
use Meilisearch\Http\Client;
use Psr\Http\Message\ResponseInterface;
use Tests\TestCase;

Expand Down Expand Up @@ -624,6 +625,28 @@ public function testGetDocumentsWithoutFilterCorrectFieldsFormat(): void
);
}

public function testGetDocumentsWithVector(): void
{
$http = new Client($this->host, getenv('MEILISEARCH_API_KEY'));
$http->patch('/experimental-features', ['vectorStore' => true]);
$index = $this->createEmptyIndex($this->safeIndexName('movies'));

$promise = $index->updateEmbedders(['manual' => ['source' => 'userProvided', 'dimensions' => 3]]);
$this->assertIsValidPromise($promise);
$index->waitForTask($promise['taskUid']);
$promise = $index->updateDocuments(self::VECTOR_MOVIES);
$this->assertIsValidPromise($promise);
$index->waitForTask($promise['taskUid']);

$response = $index->getDocuments(new DocumentsQuery());
self::assertArrayNotHasKey('_vectors', $response->getResults()[0]);
$query = (new DocumentsQuery())->setRetrieveVectors(true);
$response = $index->getDocuments($query);
self::assertArrayHasKey('_vectors', $response->getResults()[0]);

self::assertCount(5, $response);
}

public function testGetDocumentsMessageHintException(): void
{
$responseMock = $this->createMock(ResponseInterface::class);
Expand Down
16 changes: 12 additions & 4 deletions tests/Endpoints/SearchTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -694,14 +694,22 @@ public function testVectorSearch(): void
$http->patch('/experimental-features', ['vectorStore' => true]);
$index = $this->createEmptyIndex($this->safeIndexName());

$promise = $index->updateEmbedders(['default' => ['source' => 'userProvided', 'dimensions' => 1]]);
$promise = $index->updateEmbedders(['manual' => ['source' => 'userProvided', 'dimensions' => 3]]);
$this->assertIsValidPromise($promise);
$index->waitForTask($promise['taskUid']);
$promise = $index->updateDocuments(self::VECTOR_MOVIES);
$this->assertIsValidPromise($promise);
$index->waitForTask($promise['taskUid']);

$response = $index->search('', ['vector' => [-0.5, 0.3, 0.85], 'hybrid' => ['semanticRatio' => 1.0]]);

self::assertSame(5, $response->getSemanticHitCount());
self::assertArrayNotHasKey('_vectors', $response->getHit(0));

$response = $index->search('', ['vector' => [1], 'hybrid' => ['semanticRatio' => 1.0]]);
$response = $index->search('', ['vector' => [-0.5, 0.3, 0.85], 'hybrid' => ['semanticRatio' => 1.0], 'retrieveVectors' => true]);

self::assertSame(0, $response->getSemanticHitCount());
self::assertEmpty($response->getHits());
self::assertSame(5, $response->getSemanticHitCount());
self::assertArrayHasKey('_vectors', $response->getHit(0));
}

public function testShowRankingScoreDetails(): void
Expand Down
7 changes: 7 additions & 0 deletions tests/Endpoints/SimilarDocumentsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ public function testBasicSearchWithSimilarDocuments(): void
$documentId = $response->getHit(0)['id'];
$response = $this->index->searchSimilarDocuments(new SimilarDocumentsQuery($documentId));

self::assertGreaterThanOrEqual(4, $response->getHitsCount());
self::assertArrayNotHasKey('_vectors', $response->getHit(0));
self::assertArrayHasKey('id', $response->getHit(0));
self::assertSame($documentId, $response->getId());

$similarQuery = new SimilarDocumentsQuery($documentId);
$response = $this->index->searchSimilarDocuments($similarQuery->setRetrieveVectors(true));
self::assertGreaterThanOrEqual(4, $response->getHitsCount());
self::assertArrayHasKey('_vectors', $response->getHit(0));
self::assertArrayHasKey('id', $response->getHit(0));
Expand Down

0 comments on commit 0b89ce9

Please sign in to comment.