Чим семантичний пошук відрізняється від повнотекстового
Звичайний пошук на сайті шукає збіг слів: запит «як повернути кошти» не знайде статтю «політика повернення коштів», якщо в тексті немає точних слів із запиту. Семантичний пошук порівнює зміст, а не літери — він перетворює запит і текст статей на числові вектори (ембеддинги) і знаходить найближчі за змістом збіги, навіть коли слова різні.
Такий пошук корисний для бази знань, каталогу товарів і служби підтримки, де користувачі формулюють питання власними словами. Результат майже завжди точніший за повнотекстовий пошук за ключовими словами, а впровадження займає один робочий день на середньому VDS.
Як працюють ембеддинги і яку модель обрати
Модель ембеддингів перетворює текст на вектор фіксованої довжини — зазвичай від 384 до 1536 чисел. Тексти зі схожим змістом отримують близькі вектори, а відстань між векторами (косинусна подібність) показує ступінь схожості.
| Модель | Розмірність | Мови | Де запускати |
|---|---|---|---|
| all-MiniLM-L6-v2 | 384 | переважно англійська | CPU, легко |
| multilingual-e5-base | 768 | багато, включно з українською | CPU або GPU |
| text-embedding-3-small | 1536 | багато | лише через API |
Для сайту з українським і російським контентом підходить multilingual-e5-base — вона запускається локально на VDS без API-ключів і обходиться без витрат на зовнішній сервіс.
Встановлення середовища і генерація ембеддингів
Встановіть бібліотеку sentence-transformers і порахуйте вектори для всіх статей бази знань.
python3.11 -m venv /opt/search-env
source /opt/search-env/bin/activate
pip install sentence-transformers
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("intfloat/multilingual-e5-base")
texts = ["Як налаштувати резервне копіювання", "Що робити за помилки 500"]
vectors = model.encode(texts, normalize_embeddings=True)
print(vectors.shape)
Кожен виклик encode повертає масив чисел для кожного тексту. Нормалізація векторів спрощує подальше порівняння через скалярний добуток замість повного косинусного розрахунку.
Де зберігати вектори і шукати найближчі збіги
Готові вектори потрібно десь зберігати і швидко шукати серед них найближчі до запиту користувача. Є два основні шляхи: додати векторний тип прямо в наявну реляційну базу або підняти окрему спеціалізовану базу.
- Для проєкту, який уже працює на PostgreSQL, найпростіше підключити розширення — див. pgvector у PostgreSQL: один SQL-запит шукає найближчі статті без окремого сервісу.
- Для великих каталогів із мільйонами документів варто порівняти спеціалізовані векторні бази — огляд наведено у статті порівняння векторних баз даних.
- Для готової зв'язки пошуку і відповіді мовної моделі стане в пригоді схема зі статті RAG на VDS.
Як вбудувати пошук у сайт
Впровадження семантичного пошуку на наявний сайт зазвичай складається з однакових кроків незалежно від обраної бази:
- Порахувати ембеддинги для всіх поточних статей і зберегти їх разом з id матеріалу.
- Додати фонове завдання, яке перераховує вектор під час публікації або редагування статті.
- На бекенді приймати пошуковий запит, перетворювати його на вектор тією самою моделлю і шукати найближчі записи.
- Віддавати користувачу не лише заголовок, а й оцінку релевантності — це допомагає відкидати слабкі збіги нижче порогу.
Поріг зазвичай підбирають дослідним шляхом: для multilingual-e5-base гарним стартом слугує косинусна подібність вище 0.75.
Типові помилки під час впровадження
Більшість проблем пов'язані не з самою моделлю, а з організацією пайплайну навколо неї:
- Різні моделі для індексації та для пошуку — вектори з різних моделей непорівнянні, результат завжди безглуздий.
- Відсутність перерахунку ембеддингів після редагування статті — пошук знаходить застарілу версію тексту.
- Надто довгі тексти без розбиття на абзаци — модель усереднює зміст усієї статті і втрачає деталі.
- Ігнорування порогу релевантності — без відсічки пошук завжди повертає щось, навіть коли підходящої відповіді немає.
Після налаштування пайплайну семантичний пошук вдасться розширювати: додати гібридний режим зі звичайним повнотекстовим пошуком або підключити переранжування результатів окремою моделлю.