Harden vision vector search and embedding jobs.
Add point search, circuit-breaking, and safer gateway limits so artwork similarity lookups fail closed instead of hanging the request path.
This commit is contained in:
@@ -74,6 +74,43 @@ final class VectorGatewayClient
|
||||
return is_array($json) ? $json : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Store an already-computed vector directly in Qdrant.
|
||||
*
|
||||
* @param array<int, float> $vector
|
||||
* @param array<string, mixed> $metadata
|
||||
*/
|
||||
public function upsertByVector(array $vector, int|string $id, array $metadata = []): array
|
||||
{
|
||||
$response = $this->postJson(
|
||||
$this->request(),
|
||||
$this->url(
|
||||
(string) config(
|
||||
'vision.vector_gateway.upsert_vector_endpoint',
|
||||
'/vectors/upsert/vector'
|
||||
)
|
||||
),
|
||||
[
|
||||
'vector' => array_values($vector),
|
||||
'id' => (string) $id,
|
||||
'metadata' => $metadata,
|
||||
]
|
||||
);
|
||||
|
||||
if ($response->failed()) {
|
||||
throw new RuntimeException(
|
||||
$this->failureMessage(
|
||||
'Vector upsert',
|
||||
$response
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$json = $response->json();
|
||||
|
||||
return is_array($json) ? $json : [];
|
||||
}
|
||||
|
||||
public function upsertByFileContents(string $contents, string $filename, int|string $id, array $metadata = []): array
|
||||
{
|
||||
$response = $this->request()
|
||||
@@ -224,6 +261,46 @@ final class VectorGatewayClient
|
||||
return is_array($json) ? $json : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Search using an artwork vector that is already stored in Qdrant.
|
||||
*
|
||||
* Returns null when the source point does not exist so the caller may fall
|
||||
* back to the existing image/CLIP search path.
|
||||
*
|
||||
* @return list<array{id: int|string, score: float, metadata: array<string, mixed>}>|null
|
||||
*/
|
||||
public function searchByPointId(int $artworkId, int $limit = 5): ?array
|
||||
{
|
||||
try {
|
||||
$response = $this->postJson(
|
||||
$this->searchRequest(),
|
||||
$this->url(
|
||||
(string) config(
|
||||
'vision.vector_gateway.search_point_endpoint',
|
||||
'/vectors/search/point'
|
||||
)
|
||||
),
|
||||
[
|
||||
'id' => $artworkId,
|
||||
'limit' => $this->clampSearchLimit($limit),
|
||||
]
|
||||
);
|
||||
} catch (Throwable $e) {
|
||||
throw $this->classifyThrowable('search_point', $e);
|
||||
}
|
||||
|
||||
// Missing indexed vector is expected and is not a gateway failure.
|
||||
if ($response->status() === 404) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($response->failed()) {
|
||||
throw $this->classifyHttpFailure('search_point', $response);
|
||||
}
|
||||
|
||||
return $this->extractMatches($response->json());
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by upsert/delete — only ever called from queued/console indexing
|
||||
* jobs, so a more generous budget is fine.
|
||||
|
||||
Reference in New Issue
Block a user