Skip to content

Commit 2fb2f8f

Browse files
ManyTheFishnorkunas
andcommitted
V1.9 hybrid search (meilisearch#649)
* 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 <[email protected]> --------- Co-authored-by: Tomas Norkūnas <[email protected]>
1 parent 4bde6d1 commit 2fb2f8f

File tree

5 files changed

+68
-6
lines changed

5 files changed

+68
-6
lines changed

src/Contracts/DocumentsQuery.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ class DocumentsQuery
1010
private int $limit;
1111
private array $fields;
1212
private array $filter;
13+
private ?bool $retrieveVectors = null;
1314

1415
public function setOffset(int $offset): DocumentsQuery
1516
{
@@ -46,6 +47,16 @@ public function setFilter(array $filter): DocumentsQuery
4647
return $this;
4748
}
4849

50+
/**
51+
* @param bool|null $retrieveVectors boolean value to show _vector details
52+
*/
53+
public function setRetrieveVectors(?bool $retrieveVectors): DocumentsQuery
54+
{
55+
$this->retrieveVectors = $retrieveVectors;
56+
57+
return $this;
58+
}
59+
4960
/**
5061
* Checks if the $filter attribute has been set.
5162
*
@@ -84,6 +95,7 @@ public function toArray(): array
8495
'limit' => $this->limit ?? null,
8596
'filter' => $this->filter ?? null,
8697
'fields' => $this->fields(),
87-
], function ($item) { return null != $item || is_numeric($item); });
98+
'retrieveVectors' => (null !== $this->retrieveVectors ? ($this->retrieveVectors ? 'true' : 'false') : null),
99+
], function ($item) { return null !== $item; });
88100
}
89101
}

src/Contracts/SimilarDocumentsQuery.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ class SimilarDocumentsQuery
1616
private ?array $attributesToRetrieve = null;
1717
private ?bool $showRankingScore = null;
1818
private ?bool $showRankingScoreDetails = null;
19+
private ?bool $retrieveVectors = null;
1920
private ?array $filter = null;
2021

2122
/**
@@ -97,7 +98,17 @@ public function setShowRankingScoreDetails(?bool $showRankingScoreDetails): Simi
9798
}
9899

99100
/**
100-
* @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
101+
* @param bool|null $retrieveVectors boolean value to show _vector details
102+
*/
103+
public function setRetrieveVectors(?bool $retrieveVectors): SimilarDocumentsQuery
104+
{
105+
$this->retrieveVectors = $retrieveVectors;
106+
107+
return $this;
108+
}
109+
110+
/**
111+
* @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
101112
*/
102113
public function toArray(): array
103114
{
@@ -110,6 +121,7 @@ public function toArray(): array
110121
'attributesToRetrieve' => $this->attributesToRetrieve,
111122
'showRankingScore' => $this->showRankingScore,
112123
'showRankingScoreDetails' => $this->showRankingScoreDetails,
124+
'retrieveVectors' => $this->retrieveVectors,
113125
], function ($item) {
114126
return null !== $item;
115127
});

tests/Endpoints/DocumentsTest.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Meilisearch\Exceptions\InvalidArgumentException;
1212
use Meilisearch\Exceptions\InvalidResponseBodyException;
1313
use Meilisearch\Exceptions\JsonEncodingException;
14+
use Meilisearch\Http\Client;
1415
use Psr\Http\Message\ResponseInterface;
1516
use Tests\TestCase;
1617

@@ -624,6 +625,28 @@ public function testGetDocumentsWithoutFilterCorrectFieldsFormat(): void
624625
);
625626
}
626627

628+
public function testGetDocumentsWithVector(): void
629+
{
630+
$http = new Client($this->host, getenv('MEILISEARCH_API_KEY'));
631+
$http->patch('/experimental-features', ['vectorStore' => true]);
632+
$index = $this->createEmptyIndex($this->safeIndexName('movies'));
633+
634+
$promise = $index->updateEmbedders(['manual' => ['source' => 'userProvided', 'dimensions' => 3]]);
635+
$this->assertIsValidPromise($promise);
636+
$index->waitForTask($promise['taskUid']);
637+
$promise = $index->updateDocuments(self::VECTOR_MOVIES);
638+
$this->assertIsValidPromise($promise);
639+
$index->waitForTask($promise['taskUid']);
640+
641+
$response = $index->getDocuments(new DocumentsQuery());
642+
self::assertArrayNotHasKey('_vectors', $response->getResults()[0]);
643+
$query = (new DocumentsQuery())->setRetrieveVectors(true);
644+
$response = $index->getDocuments($query);
645+
self::assertArrayHasKey('_vectors', $response->getResults()[0]);
646+
647+
self::assertCount(5, $response);
648+
}
649+
627650
public function testGetDocumentsMessageHintException(): void
628651
{
629652
$responseMock = $this->createMock(ResponseInterface::class);

tests/Endpoints/SearchTest.php

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -694,14 +694,22 @@ public function testVectorSearch(): void
694694
$http->patch('/experimental-features', ['vectorStore' => true]);
695695
$index = $this->createEmptyIndex($this->safeIndexName());
696696

697-
$promise = $index->updateEmbedders(['default' => ['source' => 'userProvided', 'dimensions' => 1]]);
697+
$promise = $index->updateEmbedders(['manual' => ['source' => 'userProvided', 'dimensions' => 3]]);
698698
$this->assertIsValidPromise($promise);
699699
$index->waitForTask($promise['taskUid']);
700+
$promise = $index->updateDocuments(self::VECTOR_MOVIES);
701+
$this->assertIsValidPromise($promise);
702+
$index->waitForTask($promise['taskUid']);
703+
704+
$response = $index->search('', ['vector' => [-0.5, 0.3, 0.85], 'hybrid' => ['semanticRatio' => 1.0]]);
705+
706+
self::assertSame(5, $response->getSemanticHitCount());
707+
self::assertArrayNotHasKey('_vectors', $response->getHit(0));
700708

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

703-
self::assertSame(0, $response->getSemanticHitCount());
704-
self::assertEmpty($response->getHits());
711+
self::assertSame(5, $response->getSemanticHitCount());
712+
self::assertArrayHasKey('_vectors', $response->getHit(0));
705713
}
706714

707715
public function testShowRankingScoreDetails(): void

tests/Endpoints/SimilarDocumentsTest.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ public function testBasicSearchWithSimilarDocuments(): void
3232
$documentId = $response->getHit(0)['id'];
3333
$response = $this->index->searchSimilarDocuments(new SimilarDocumentsQuery($documentId));
3434

35+
self::assertGreaterThanOrEqual(4, $response->getHitsCount());
36+
self::assertArrayNotHasKey('_vectors', $response->getHit(0));
37+
self::assertArrayHasKey('id', $response->getHit(0));
38+
self::assertSame($documentId, $response->getId());
39+
40+
$similarQuery = new SimilarDocumentsQuery($documentId);
41+
$response = $this->index->searchSimilarDocuments($similarQuery->setRetrieveVectors(true));
3542
self::assertGreaterThanOrEqual(4, $response->getHitsCount());
3643
self::assertArrayHasKey('_vectors', $response->getHit(0));
3744
self::assertArrayHasKey('id', $response->getHit(0));

0 commit comments

Comments
 (0)