Qdrant PHP Client

Векторный поиск в PHP: граница между моделью, приложением и базой.

PHP-клиент к Qdrant: фильтрованный поиск, коллекции и точки через заменяемый HTTP-транспорт. Разбор совместимости, формы ответа и границ индексации.

PHP · Qdrant · Vector Search · HTTP

Моя роль

Автор библиотеки: PHP API, HTTP-транспорт, обработка ошибок, примеры и тесты.

Open source · Сентябрь 2026. Разбор опубликованного кода на коммите 3b1c8ab0. Ссылки закреплены на этой версии; ограничения описаны для неё.

Векторный поиск внутри PHP-приложения

Я написал Qdrant PHP Client как отдельную библиотеку для работы с векторной базой по HTTP. Её задача — связать PHP-приложение с коллекциями, точками и поиском Qdrant. Генерация эмбеддингов, предметные модели и правила доступа остаются в приложении. Это позволяет подключать поиск к существующему бэкенду постепенно, без переноса всей бизнес-логики в другой сервис.

Моя роль — автор библиотеки: публичный API, транспорт, обработка ошибок, примеры и тесты. В composer.json заявлены PHP ^7.2|^8.0, расширения cURL и JSON.

От текста к поисковому результату
  1. PHP-приложениеМодель эмбеддингов, документ и права доступа
  2. Qdrant PHP ClientКоллекции, точки, фильтры и HTTP-запросы
  3. QdrantХранение векторов и поиск соседей

Модель эмбеддингов находится за пределами клиента. Назад приложение получает идентификаторы, оценки сходства и запрошенный payload.

Сценарий: похожие статьи на выбранном языке

Для каталога статей приложение сначала получает эмбеддинг текста, сохраняет его как vector, а язык и идентификатор материала — как payload. При поиске вектор запроса должен быть построен той же моделью и иметь размерность коллекции. Фильтр по языку передаётся в Qdrant вместе с запросом: отбор выполняется до возврата результатов, а не после получения пяти потенциально неподходящих статей.

Ниже самостоятельный пример чтения для заранее заполненной коллекции case_articles с размерностью 4 и метрикой Cosine. Четыре числа — синтетический вектор для проверки API, не реальный эмбеддинг и не демонстрация качества семантического поиска. У точек должен быть строковый payload locale.

<?php
require __DIR__ . '/vendor/autoload.php';

use Tenqz\Qdrant\QdrantClient;
use Tenqz\Qdrant\Transport\Infrastructure\Factory\CurlHttpClientFactory;

$http = (new CurlHttpClientFactory())->create('127.0.0.1', 6333);
$client = new QdrantClient($http);
$filter = ['must' => [
    ['key' => 'locale', 'match' => ['value' => 'ru']],
]];

$response = $client->search(
    'case_articles', [0.1, 0.2, 0.3, 0.4], 5, $filter
);
foreach ($response['result'] as $hit) {
    echo $hit['id'] . ' ' . $hit['score'] . PHP_EOL;
}

Клиент возвращает весь JSON-ответ Qdrant, поэтому результаты находятся в $response['result']. Код не подменяет оценку сходства вероятностью релевантности. Составление ссылки на статью и окончательная проверка доступа происходят в вызывающем приложении.

Решение 1: небольшой API поверх явного транспорта

QdrantClient принимает HttpClientInterface. Фасад формирует HTTP-метод, путь и тело операции, а cURL-реализация отвечает за соединение, JSON и заголовок API-ключа. В тесте можно заменить транспорт и проверить конкретный запрос, не запуская векторную базу. В приложении этот же интерфейс оставляет точку для собственного HTTP-адаптера.

Решение 2: сохранять форму ответа провайдера

Возвращаемые массивы сохраняют ответ API вместе с его служебными полями. Такой подход облегчает просмотр исходных данных и добавление прикладной обработки, но переносит проверку вложенной структуры на вызывающий код. Здесь нет DTO для каждой комбинации фильтров и результата; границу между библиотекой и предметной моделью нужно обозначить в приложении.

Решение 3: различать причины неудачного запроса

В транспорте выделены NetworkException, HttpException и SerializationException. Это позволяет отдельно обработать сбой соединения, отказ API и невозможность прочитать JSON. Разбор JSON происходит до проверки HTTP-статуса: HTML-ответ прокси может проявиться как ошибка сериализации. Автоматических повторов здесь нет; политика повторной записи остаётся решением вызывающего кода.

Что можно проверить в исходниках

Результат работы — устанавливаемый Composer-пакет с операциями создания коллекций, загрузки точек, фильтрованного поиска, рекомендаций и пакетного поиска. Фасад показывает точные тела запросов. HTTP-транспорт раскрывает тайм-аут и обработку ответов. В unit-тестах есть ожидания HTTP-метода, endpoint и параметров через подставной транспорт.

Область unit-тестов — состав параметров, маршрутизация операций и передача ответа через интерфейс транспорта. Качество поиска оценивается отдельно на запросах и размеченных результатах конкретного приложения; пропускная способность зависит также от конфигурации сервера и данных.

Границы реализации

Клиент не вычисляет эмбеддинги, не синхронизирует индекс с основной базой и не предоставляет все новые возможности Qdrant автоматически. Например, upsertPoints не принимает параметр ожидания применения записи: успешный ответ на загрузку нельзя без проверки считать подтверждением её немедленной видимости. Размерность, жизненный цикл коллекций и согласование удалений остаются частью интеграции.

Как попробовать

Установите пакет и подготовьте отдельный Qdrant для эксперимента. Для создания и заполнения тестовой коллекции используйте пример из репозитория; он выполняет операции записи, поэтому не направляйте его на рабочие данные. Затем выполните показанный выше запрос к своей подготовленной коллекции.

composer require tenqz/qdrant

Подробности установки и обработки ошибок разобраны в статье о Qdrant PHP Client. Исходники и история изменений доступны в tenqz/qdrant.

GitHub Инструкция подключения

Давайте делать сложное понятным.

Архитектура, инженерное лидерство и AI в разработке — когда система слишком важна, чтобы её упрощать, и слишком дорогая, чтобы ею не владеть.

LinkedIn Telegram Email