«Покажите похожие инструкции, но без архивных обходных путей»: поиск по примерам в Qdrant
Инженер открывает в базе знаний два подходящих руководства по восстановлению связи. Одно написано как краткая памятка, другое описывает полную процедуру для площадки. В прошлой выдаче рядом с ними были старые обходные способы, которые инженер пометил как неподходящие. Теперь он просит показать ещё источники. Поиск по одному текстовому запросу плохо передаёт, что оба формата устраивают, а документы про обходной способ следует опустить.
Как поисковик использует примеры
Возьмём векторы двух удачных источников и одного неподходящего. Если интерфейс передаёт идентификаторы точек, Qdrant сам найдёт их векторы. Мы получим новые кандидаты из той же коллекции. В клиенте для этого используется query_points с RecommendQuery. Векторы примеров и кандидатов должны описывать документы в одном представлении. Если проиндексировать часть документов другой моделью, сравнение потеряет общий смысл даже при одинаковой размерности.
У стратегии average_vector положительные примеры сворачиваются в средний вектор. При наличии отрицательных запрос смещается от их среднего. Такой запрос удобен, если мы ищем общую область сходства. Когда удачные примеры относятся к двум разным группам, их центр может лучше соответствовать общему обзору, чем любой из нужных типов инструкций.
best_score сравнивает кандидата с каждым примером. Для него важны лучшее положительное и лучшее отрицательное совпадения. Если положительное сильнее, кандидат получает положительную оценку, иначе отрицательную. Кандидат может хорошо совпасть с одной из двух удачных инструкций, даже если второй он совсем не похож. При большом числе примеров сравнения дорожают, поэтому начните с небольшого числа показательных документов.
Сравним два порядка выдачи
Запустите пример с пакетом qdrant-client==1.20.0. Коллекция работает локально в памяти. Три координаты условно передают сходство с памяткой, регламентом и обходным способом. Документ «Обзор» похож сразу на оба положительных примера. Две новые инструкции почти совпадают каждая со своим примером. Обходной способ с нужной терминологией имеет небольшую общность с памяткой, но ближе к отрицательному образцу.
from qdrant_client import QdrantClient, models as m
client = QdrantClient(":memory:")
collection = "guides"
client.create_collection(
collection, vectors_config=m.VectorParams(size=3, distance=m.Distance.COSINE)
)
vectors = {
1: ("Пример памятки", [1.0, 0.0, 0.0]),
2: ("Пример регламента", [0.0, 1.0, 0.0]),
3: ("Пример обхода", [0.0, 0.0, 1.0]),
4: ("Новая памятка", [0.98, 0.0, 0.1]),
5: ("Новый регламент", [0.0, 0.96, 0.12]),
6: ("Обзор", [0.70, 0.70, 0.04]),
7: ("Новый обход", [0.4, 0.0, 0.91]),
}
client.upsert(collection, [
m.PointStruct(id=i, vector=v, payload={"title": title})
for i, (title, v) in vectors.items()
])
def recommend(strategy):
points = client.query_points(
collection,
query=m.RecommendQuery(
recommend=m.RecommendInput(positive=[1, 2], negative=[3], strategy=strategy)
),
limit=4, with_payload=True,
).points
print(strategy.value, [(p.payload["title"], round(p.score, 3)) for p in points])
return points
average = recommend(m.RecommendStrategy.AVERAGE_VECTOR)
best = recommend(m.RecommendStrategy.BEST_SCORE)
assert average[0].id == 6 and {p.id for p in best[:2]} == {4, 5}
assert best[-1].id == 7 and best[-1].score < 0
client.close()
На первом месте при усреднении появляется обзор. При best_score первыми становятся обе инструкции. Последний результат получает отрицательную оценку: он ближе к отрицательному примеру. Сами точки, переданные как примеры, Qdrant исключает из результатов этого запроса. Так можно предлагать новые документы после уже просмотренных.
Где провести границу между фильтром и оценкой
Отрицательный пример нужен, когда человек может узнать нежелательный тип по содержанию, но у документов нет готового поля для фильтра. Если архивный документ явно помечен как недействующий, поставьте условие по метаданным. Для прав доступа тоже требуется фильтр и проверка полномочий на сервере, в том числе для идентификаторов, которые пользователь прислал как примеры. Похожесть влияет на место в выдаче. Обязательные условия определяют, имеет ли точка право туда попасть.
На реальной базе сохраните несколько сеансов с двумя различающимися подходящими источниками и явным отрицательным. Для каждого прогона отметьте, сколько новых инструкций из обеих групп вышло в первые позиции. Сравните с обычным поиском по запросу и обеими стратегиями рекомендаций. Если затем результаты пойдут в RAG, проверьте, что переданные фрагменты действительно отвечают на исходный вопрос. Обратная связь о похожести может вернуть хорошие документы по смежной теме.
Практика на Latorn
Откройте пробный урок «Qdrant на практике», чтобы разобраться с коллекцией и поисковыми запросами перед экспериментом со своими документами.
В платном курсе «RAG на Python» вы настроите поиск в Qdrant и фильтры, сравните выдачу с гибридным поиском и подключите выбранные источники к LLM. Посмотреть программу и практикум по Qdrant.
Продолжить на практике
- RAG на Python: векторный поиск и ответы по своим документам ↗
Создавайте поиск и LLM-ассистентов по своим документам. Практический курс RAG на Python: FAISS, Qdrant, Weaviate, гибридный поиск и проверка качества. Научитесь находить нужные фрагменты и подключать их к модели. Есть практикумы и пробные уроки.
