Семантичний пошук у PostgreSQL за допомогою pgvector та Node.js — без необхідності в LLM
Семантичний пошук у PostgreSQL за допомогою pgvector та Node.js без ШІ: ембеддинги MiniLM, чанки, індекс IVFFlat, оператори відстані та спосіб читання оцінок.
Джерела: Talk to Your Database Like a Human — No LLM Required: Semantic Search with Node.js + PostgreSQL
База даних може відповідати на запитання, поставлені звичайною англійською мовою, без використання будь-якої мовної моделі. Це стає можливим завдяки векторному пошуку. За допомогою Node.js, PostgreSQL та розширення pgvector можна створити систему, яка знаходить відповіді за метою запиту, а не за ключовими словами, причому єдиною моделлю, яка використовується, є невелика модель ембеддингів, яка перетворює текст на числа.
Реляційні бази даних завжди добре справлялися з зберіганням та отриманням даних, за умови, що ви ставите саме правильні запитання. Точні зіставлення, фільтри та структуровані запити є потужними, але обмеженими. Векторні бази даних, здається, вирішують іншу проблему: пошук у неструктурованому контенті за його значенням, а не за словами, які він містить.
Чотири терміни, які варто зрозуміти
Токен. Найменша одиниця тексту, з якою працює модель. Токени не завжди є цілими словами. Це може бути повне слово, наприклад "hello", фрагмент (тож "unbelievable" може розділитися на "un", "believ" та "able"), окремий символ, як "!", або частина розділового знака чи пробілу. Фраза на кшталт "ChatGPT is great" може бути розділена на "Chat", "G", "PT", " is" та " great".
Чанк. Невелика, самодостатня частина більшого документа, зазвичай кілька речень або один абзац. Вставка всього документа одночасно працює погано, тому його спочатку розділяють на чанки. Розділення на чанки прискорює обробку, підвищує точність пошуку та забезпечує актуальність результатів для запиту.
Ембеддинг. Числовий аналог тексту, зображення чи аудіо, який відображає його сенс. Його створює модель машинного навчання, наприклад MiniLM. Ембеддинг можна розглядати як суть даних.
Вектор. Форма, у якій фактично зберігається ембеддинг: масив чисел.
[0.2, -0.5, 0.9, ...]
Це форма, яка зберігається в пам’яті та в PostgreSQL після встановлення розширення на кшталт pgvector.
Основна ідея полягає у наступному: слова, речення чи зображення перетворюються на ембеддинги. Об’єкти з схожими значеннями мають вектори, які знаходяться близько один до одного, тоді як неспоріднені об’єкти — далі один від одного. Рядок на кшталт „Hello world“ перетворюється на довгий список чисел з плаваючою комою:
// "Hello world" turns into this embedding:
const embedding = [0.01, -0.42, 0.15, ..., 0.99]; // ← this is a vector
і цей список потім зберігається поруч із оригінальним текстом:
INSERT INTO documents (content, embedding)
VALUES ('Hello world', embedding);
Чому реляційна база даних недостатня
Традиційна RDBMS працює з таблицями, рядками та стовпцями. Вона без проблем обробляє запити на кшталт „усі тикети зі статусом OPEN“ чи „користувачі, створені після 2024 року“. Однак сучасні додатки також мають справу з документами, розмовами, зображеннями та аудіо. Точне зіставлення майже нічого не дає у цих випадках.
Векторна база даних зберігає ембеддинги разом із даними та знаходить елементи за схожістю та контекстом. Тож замість того, щоб шукати документи, які містять слово „error“, можна шукати документи про проблеми з автентифікацією та отримати їх навіть у тому випадку, якщо слово „error“ ніколи не з’являється. Порівняння відбувається за математичною відстанню між векторами, а не за зіставленням тексту.
Звичайний процес виглядає так:
- Надходить сирий контент: документи, тикети чи щось інше.
- Модель ембеддингу перетворює його на вектори.
- Вектори зберігаються, наприклад, у PostgreSQL за допомогою pgvector.
- Індекс найближчих сусідів (ANN) забезпечує швидке пошукове запитування.
- Запит користувача також перетворюється на вектор.
- База даних повертає вектори, які знаходяться найближче до нього, тобто ті, що мають найбільшу схожість за значенням.
Що це дозволяє:
- Семантичний пошук, заснований на значенні запиту, а не лише на його точних словах.
- Довгострокову пам’ять для LLM, шляхом зберігання попередніх взаємодій, документів чи фактів, які модель може згадати, навіть якщо вони не були в її навчальних даних.
- Рекомендації, шляхом пошуку елементів чи поведінки, які схожі один на одного у просторі ембеддингів.
- Пошук схожості в тексті, зображеннях, аудіо чи відео.
PostgreSQL як сховище векторів
Вам не потрібно впроваджувати нову базу даних для всього цього. За допомогою pgvector PostgreSQL може безпосередньо зберігати ембеддинги, виконувати запити на схожість та використовувати індекси, такі як IVFFlat, щоб зберігати швидкість роботи. База даних, яку ви вже використовуєте, просто отримує нову функціональність — від зберігання даних до можливості порівнювати їхнє значення. Пошук більше не полягає у зіставленні слів, а у зіставленні значень.
Поетапна налаштування
1. Встановіть PostgreSQL та увімкніть pgvector. Встановіть PostgreSQL з офіційної сторінки завантаження, під’єднайтеся та увімкніть розширення:
CREATE EXTENSION IF NOT EXISTS vector;
2. Створіть таблицю документів. Вона містить сирий текст та його ембеддинг. Число 384 у визначенні — це розмір вихідних даних моделі all-MiniLM-L6-v2.
-- Note: 384 is the embedding size output by all-MiniLM-L6-v2
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
content TEXT,
embedding VECTOR(384)
);
3. Додайте векторний індекс. Щоб зберегти ефективність пошуку за схожістю, використовуйте індекс найближчих сусідів приблизно:
CREATE INDEX documents_embedding_idx
ON documents
USING ivfflat (embedding vector_l2_ops)
WITH (lists = 100);
Цей підхід використовує IVFFlat для швидких приблизних пошуків, вимірює відстані за методом L2 (евклідовою) та ділить вектори на 100 кластерів.
4. Підберіть оператор запиту до індексу. Оператор у вашому запиті має збігатися з класом операторів, за допомогою якого було створено індекс. pgvector пропонує кілька операторів, кожен з яких має власний клас. У цьому прикладі використовується оператор <#>, а також налаштовується параметр vector_l2_ops. Зверніть увагу, що в документації pgvector відстань L2 зазвичай позначається за допомогою <->, а <#> — це від’ємний скалярний добуток, тому переконайтеся, що ваш запит та індекс узгоджені.
5. Запустіть проект. Повний працюючий приклад знаходиться у репозиторії на GitHub під назвою vectorgarquer/vectorized-database-embeddings. Клонуйте або створіть форк цього репозиторію, потім встановіть необхідні залежності:
npm install
Копіюйте файл .env.example у файл .env у корені проекту та введіть свої дані підключення до PostgreSQL. Потім запустіть його:
npm start
6. Спостерігайте, як він шукає. Як тільки програма запущена, вона під’єднується, вставляє ембеддинги та виконує семантичні пошуки без додаткових введень. Після цього ви можете надавати їй власні дані та запити. У прикладі наведено пошук фрази „Що означає генеративний ШІ?“, а результати, знайдені в базі даних, відображаються ось так:
Search Results:
[1] Distance: -0.7562
n be represented in another modality such as text.
2.2 A Model-, System-, and Application-Level View
of Generative AI
2.2.1 Model-Level View
A generative AI model is a type of machine learning
architecture that uses AI algorithms to create novel data
instances, drawing upon the patterns and relationships
observed in the training data. A generative AI model is of
critically central yet incomplete nature, as it requires fur-
ther fine-tuning to specific tasks thro
[2] Distance: -0.7562
n be represented in another modality such as text.
2.2 A Model-, System-, and Application-Level View
of Generative AI
2.2.1 Model-Level View
A generative AI model is a type of machine learning
architecture that uses AI algorithms to create novel data
instances, drawing upon the patterns and relationships
observed in the training data. A generative AI model is of
critically central yet incomplete nature, as it requires fur-
ther fine-tuning to specific tasks thro
[3] Distance: -0.7562
n be represented in another modality such as text.
2.2 A Model-, System-, and Application-Level View
of Generative AI
2.2.1 Model-Level View
A generative AI model is a type of machine learning
architecture that uses AI algorithms to create novel data
instances, drawing upon the patterns and relationships
observed in the training data. A generative AI model is of
critically central yet incomplete nature, as it requires fur-
ther fine-tuning to specific tasks thro
[4] Distance: -0.7562
n be represented in another modality such as text.
2.2 A Model-, System-, and Application-Level View
of Generative AI
2.2.1 Model-Level View
A generative AI model is a type of machine learning
architecture that uses AI algorithms to create novel data
instances, drawing upon the patterns and relationships
observed in the training data. A generative AI model is of
critically central yet incomplete nature, as it requires fur-
ther fine-tuning to specific tasks thro
[5] Distance: -0.7094
assistants, personalized education and service, and digital
art. As such, generative AI has substantial implications for
BISE practitioners and scholars as an interdisciplinary
research community. In our Catchword article, we offered
a conceptualization of the principles of generative AI along
a model-, system-, and application-level view as well as a
social-technical view and described limitations of current
generative AI. Ultimately, we provided an impactful
rese
Читання результатів
Після виконання програми ви отримуєте список у такому вигляді:
Search Results:
[1] Distance: -0.7562
...
[5] Distance: -0.7094
...
Відстань вказує на те, наскільки близько збережений фрагмент знаходиться до ембеддингу запиту. І фрагмент, і запит перетворюються на вектори, і PostgreSQL з pgvector вимірює відстань між ними. Правило просте: чим менша відстань, тим більш схожий контент.
Значення є від’ємними, наприклад:
-0.7562
Це тому, що оператор <#> повертає заперечене значення, тож звичайний сортування розміщує найближчі записи на початку. На практиці чим більш негативне число, тим ближчий та актуальніший збіг, а число, ближче до нуля, вказує на менш сильний збіг.
Якщо подивитися на рейтинг, результати з номерами 1 до 4 мають однаковий бал -0.7562, тому вони однаково актуальні для запиту. Результат номер 5 має бал -0.7094, що також є актуальним, але з меншою схожістю.
Ви також можете помітити кілька результатів із майже ідентичним текстом. Це цілком очікувано. Вихідний документ був розділений на фрагменти, сусідні фрагменти перекриваються або повторюють схожий контент, і кожен з них має власне вбудовування.
Що показує результат
Навіть у відсутності LLM під час запиту система все одно розуміла сенс, а не лише ключові слова, знаходила текст, який відповідав контексту, та ранжувала його за векторною схожістю. Отримані уривки були згруповані навколо моделей генеративного ШІ, рівня моделі та архітектури машинного навчання, тож пошук чітко функціонував на рівні концепцій, а не точних слів.
Результатом є семантичний пошуковий двигун, який існує всередині PostgreSQL. Для виконання запитів не потрібен LLM, немає окремої векторної бази даних, а ембеддинги разом із pgvector виконують усю роботу.
Пов’язана література
- Семантичне кешування для агентів LLM за допомогою Redis: як скоротити витрати та затримки — Як семантичне кешування зменшує витрати та затримки у роботі LLM: використання ембеддингів, порогових значень, Redis та RedisVL, налаштування точності та кешування підзапитів у межах робочих процесів агентів.
- Чому агентам для аналітики ШІ потрібен семантичний шар замість сирого SQL — Перетворення тексту на SQL у сирих таблицях складу створює вигадані метрики та ігнорує правила доступу. Дізнайтеся, як семантичний шар, такий як Cube у поєднанні з MCP, надає агентам управлінський сенс даних.