#15 — Реалізація пошуку kNN в Elasticsearch для вбудованих документів

pic

Цю картину створив автор цього блогу.

Вступ

У попередній статті ми досліджували, як вкладати документи за допомогою моделей глибокого навчання та зберігати ці вектори в Elasticsearch.
Тепер ми зробимо ще крок далі, реалізувавши пошук за допомогою алгоритму k-найближчих сусідів (kNN), щоб отримувати документи на основі їх щільних векторних уявлень.

Для детальнішого пояснення перегляньте відео-урок:

Відео-урок: Алгоритм пошуку kNN.

Всі пов’язані з цим ноутбуки та слайди можна знайти в моєму репозиторії на GitHub:

[

GitHub - ImadSaddik/ElasticSearchPythonTutorial: Цей репозиторій містить ноутбуки, що демонструють…

Цей репозиторій містить ноутбуки, що демонструють використання ElasticSearch у Python, супроводжувані відповідними відео на YouTube…

github.com

](https://github.com/ImadSaddik/ElasticSearchPythonTutorial?source=post_page-----17f3b9b82017--------------------------------)

Що таке пошук kNN?

Пошук kNN — це метод, що використовується для знаходження k найближчих сусідів до запитуваного вектору в наборі даних.
В Elasticsearch це працює з полями щільних векторів і використовує параметр knn для пошуку.

Примітка: Стандартний query параметр тут не застосовується.

Як це працює?

Спочатку вам потрібно використовувати модель вбудовування (embedding), щоб перетворити ваші документи в щільні векторні уявлення. Ознайомтесь з попередньою статтею, щоб дізнатися, як це зробити.

Ось приклад з трьома документами:

document_1 = {  
 "id": 1,  
 "title": "Сонячна система",  
 "content": "Сонячна система складається з Сонця та об'єктів, що обертаються навколо нього, включаючи вісім планет, їхні супутники, карликові планети та безліч малих тіл, таких як астероїди і комети."  
}  

document_2 = {  
 "id": 2,  
 "title": "Чорні діри",  
 "content": "Чорна діра — це область простору, де гравітаційне тяжіння таке сильне, що нічого, навіть світло, не може покинути її."  
}
Вони утворюються, коли масивні зірки колапсують під дією власної гравітації."  
}  

document_3 = {  
 "id": 3,  
 "title": "Галактики",  
 "content": "Галактики — це величезні системи, які складаються з зірок, залишків зірок, міжзоряного газу, пилу та темної матерії."  
}
Молочний Шлях — це галактика, що містить нашу Сонячну систему."  
}  

Використовуйте модель all-MiniLM-L6-v2 для кодування поля content кожного документа:

import torch  
from sentence_transformers import SentenceTransformer  

# Завантаження моделі  
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')  
model = SentenceTransformer('all-MiniLM-L6-v2')  
model = model.to(device)  

# Кодування поля content для кожного документа  
document_1["embedding"] = model.encode(document_1["content"])  
document_2["embedding"] = model.encode(document_2["content"])  
document_3["embedding"] = model.encode(document_3["content"])  

Створіть новий індекс, де поле embedding буде встановлено як dense_vector, і вставте документи:

from elasticsearch import Elasticsearch  

# Підключення до Elasticsearch  
es = Elasticsearch('http://localhost:9200')  

# Створення індексу  
response = es.indices.create(  
 index="my_index",  
 mappings={  
 "properties": {  
 "embedding": {  
 "type": "dense_vector",  
 }  
 }  
 },  
)  

# Індексація документів  
response = es.index(index="my_index", body=document_1)  
response = es.index(index="my_index", body=document_2)  
response = es.index(index="my_index", body=document_3)  

Коли ви ставите запитання, наприклад, Що таке чорні діри?, ми не можемо безпосередньо використовувати цей текст для пошуку відповідних документів.
Натомість, запит має бути закодований за допомогою тієї ж моделі.

Тут алгоритм kNN демонструє свою ефективність, оскільки працює з вбудованими (embedded) представленнями. Використовуючи різні метрики відстані, kNN визначає документи, найближчі до вбудованої версії запиту.

pic

Різні метрики відстані, джерело: Jonte Dancker.

Після того як відстані між запитом та документами обчислені, вони сортуються у порядку зростання.
Алгоритм kNN дозволяє вказати кілька параметрів для тонкої налаштування процесу пошуку:

  • field: Поле повинно бути відображено як dense_vector.
  • query_vector: Представляє вбудоване (embedding) представлення тексту запиту.
  • num_candidates: Максимальна кількість документів, які будуть отримані перед застосуванням алгоритму kNN.
  • k: Кількість найближчих документів, які слід повернути.

Підсумовуючи, це основна функціональність алгоритму kNN.

Виконання пошуку kNN

Давайте реалізуємо пошук kNN, щоб знайти документи, пов'язані з запитом.

Приклад запиту 1

query = "Що таке чорна діра?"  
embedded_query = model.encode(query)  

result = es.search(  
 index='my_index',  
 knn={  
 "field": "embedding",  
 "query_vector": embedded_query.tolist(),  
 "num_candidates": 5,  
 "k": 3,  
 }  
)  
for hit in result.body["hits"]["hits"]:  
 print(f"Назва : {hit['_source'].get('title', 'Без назви')}")  
 print(f"Зміст: {hit['_source']['content']}")  
 print(f"Оцінка : {hit['_score']}")  
 print("*"*100)

Оскільки питання стосувалося чорних дір, перший документ отримує найвищу оцінку, оскільки він спеціально обговорює чорні діри.

Назва : Чорні діри  
Зміст: Чорна діра — це область простору, де гравітаційне притягання настільки сильне, що нічого, навіть світло, не може вирватися з неї.
Вони утворюються, коли масивні зірки колапсують під власною гравітацією.  
Оцінка : 0.8863337  
****************************************************************************************************  
Назва : Темна матерія  
Зміст: Темна матерія — це тип матерії, яка не випромінює світло чи енергію. Її неможливо спостерігати безпосередньо, але вважається, що вона складає близько 27% загальної маси та енергії Всесвіту.  
Оцінка : 0.6618407  
****************************************************************************************************  
Назва : Галактики  
Зміст: Галактики — це величезні системи, що складаються зі зірок, залишків зірок, міжзоряного газу, пилу та темної матерії. Чумацький Шлях — це галактика, яка містить нашу Сонячну систему.
Оцінка : 0.64313364  
****************************************************************************************************  

Приклад запиту 2

query = "Як ми знаходимо екзопланети?"  
embedded_query = get_embedding(query)  

result = es.search(  
 index='my_index',  
 knn={  
 "field": "embedding",  
 "query_vector": embedded_query.tolist(),  
 "num_candidates": 5,  
 "k": 1,  
 }  
)  
for hit in result.body["hits"]["hits"]:  
 print(f"Назва : {hit['_source'].get('title', 'Без назви')}")  
 print(f"Зміст: {hit['_source']['content']}")  
 print(f"Оцінка : {hit['_score']}")  
 print("*"*100)

Встановивши параметр k на 1, ми отримали лише один документ.

Назва : Екзопланети  
Зміст: Екзопланети, або екзосонячні планети, — це планети, які існують поза межами нашої Сонячної системи. Вони сильно відрізняються за розмірами та складом і часто знаходяться за допомогою таких методів, як метод транзитів та радіальна швидкість.
Оцінка : 0.85655975  
****************************************************************************************************  

Результати показують, що знайдені документи є дуже релевантними до запиту. Щоб ще більше уточнити пошук, можна встановити поріг оцінки, щоб виключити нерелевантні документи.

Документація

Для більш детальної інформації про пошук kNN в Elasticsearch, зверніться до офіційної документації.

Наступні кроки

Тепер, коли ви розумієте, як працює пошук kNN, ви можете створювати чудові пошукові системи з семантичним пошуком. У наступному відео ми розглянемо глибоку пагінацію.

Для більш детальних порад, перегляньте відеоурок:

Відеоурок: Глибока пагінація: Пошук після VS From/Size.

Альтернативно, продовжуйте читати наступну статтю в цій серії на Medium.

Перекладено з: #15 — Implementing kNN search in Elasticsearch for embedded documents

Leave a Reply

Your email address will not be published. Required fields are marked *