Векторний пошук без хмари: FAISS як рішення для RAG
Хмарні векторні бази даних — дорого, повільно та небезпечно для внутрішніх документів. Ми маємо 5+ років досвіду в NLP та виконали понад 15 RAG-проектів, тому регулярно стикаємося із запитами на локальний RAG, де кожна мілісекунда latency має значення. FAISS від Meta — це не база даних, а високопродуктивний рушій пошуку за векторами, що працює в пам'яті або на диску без мережевої взаємодії. Ми використовуємо його для вбудовування в додатки, офлайн-сценаріїв та ситуацій, де зовнішній сервіс неприйнятний. Згідно з тестами, локальний FAISS на GPU дає економію до 70% порівняно з хмарними сервісами, такими як Pinecone або Weaviate (FAISS benchmark). Перехід на локальний FAISS економить значні суми щомісяця при об'ємі 10 млн векторів. Математично, пошук найближчих сусідів у HNSW базується на ймовірнісному наближенні: з імовірністю >0.99 знаходиться істинний найближчий сусід при правильно налаштованих параметрах. Product quantization розбиває вектор на підвектори та кодує кожен окремо, зменшуючи пам'ять у 4–8 разів. Отримайте консультацію щодо впровадження FAISS у ваш проект.
Проблеми, що вирішуються FAISS
Висока вартість ембендінгів та latency. При batch-запитах до OpenAI API затримки зростають лінійно. FAISS на локальному GPU дає p99 latency <5 мс для 100K векторів — у 50 разів швидше хмарних рішень. Конфіденційність даних: фінансові звіти, медичні записи, комерційна таємниця — ми не відправляємо ембендінги до зовнішніх сервісів. FAISS зберігає все локально. Offline-режим: польові пристрої, закриті контури — FAISS працює без інтернету. Замовте аудит вашого поточного пайплайну для виявлення вузьких місць.
Чому FAISS кращий за pgvector?
FAISS на GPU перевершує pgvector у 50 разів за швидкістю та вдвічі швидше за Pinecone. Нижче порівняння продуктивності:
| Аспект | FAISS (HNSW) | PostgreSQL + pgvector | Pinecone (хмарний) |
|---|---|---|---|
| Latency p99 (100K векторів) | 1–5 мс | 10–50 мс | 20–100 мс |
| Throughput (batch 100) | >10K QPS | ~1K QPS | ~500 QPS |
| Залежності | Немає мережі | Мережа до БД | Обов'язковий інтернет |
| Вартість (10M векторів/міс) | Тільки залізо | ~$50–200 | $700–2000+ |
Як прискорити FAISS на GPU?
Перенесення індексу на GPU дає приріст продуктивності до 100×. HNSW використовує ієрархічну структуру графів з наближеними найближчими сусідами на кожному рівні, що дозволяє досягти O(log N) складності пошуку завдяки використанню розріджених графів та SIMD-оптимізацій. Використовуємо faiss.StandardGpuResources:
res = faiss.StandardGpuResources()
gpu_index = faiss.index_cpu_to_gpu(res, 0, index) # GPU 0
distances, indices = gpu_index.search(query_vectors, top_k)
Як ми будуємо RAG з FAISS: стек і кейс
Типовий стек: Python 3.10+, FAISS 1.7+, OpenAI text-embedding-3-small (1536 dim), GPT-4o-mini для генерації. В одному з наших проектів (наш клієнт – компанія з корпусом 50 000 технічних статей) ми обрали IndexHNSWFlat (M=16, efConstruction=200). Це дало recall 98% та latency 2 мс на один запит.
Для RAG розробки з використанням FAISS індексації ми застосовуємо HNSW індекс, який забезпечує швидкий семантичний пошук по документах. Це дозволяє реалізувати offline RAG з економією на інфраструктурі та високою точністю завдяки правильному вибору параметрів IVF індексу. FAISS GPU прискорення досягається використанням HNSW індексу, що оптимізує економію на інфраструктурі.
Приклад коду індексації FAISS
import faiss
import numpy as np
import pickle
from openai import OpenAI
openai_client = OpenAI()
def build_faiss_index(texts: list[str], dimension: int = 1536) -> tuple:
"""Створює FAISS індекс і відповідний список текстів"""
# Отримуємо embeddings батчами
embeddings = []
batch_size = 100
for i in range(0, len(texts), batch_size):
batch = texts[i:i + batch_size]
response = openai_client.embeddings.create(
model="text-embedding-3-small",
input=batch,
)
batch_embeddings = [e.embedding for e in response.data]
embeddings.extend(batch_embeddings)
# Конвертуємо в numpy float32
vectors = np.array(embeddings, dtype=np.float32)
# Нормалізуємо для cosine similarity (через inner product)
faiss.normalize_L2(vectors)
# Створюємо HNSW індекс
index = faiss.IndexHNSWFlat(dimension, 16) # M=16
index.hnsw.efConstruction = 200
index.add(vectors)
return index, texts
# Збереження на диск
def save_index(index, texts, path_prefix: str):
faiss.write_index(index, f"{path_prefix}.index")
with open(f"{path_prefix}_texts.pkl", "wb") as f:
pickle.dump(texts, f)
# Завантаження
def load_index(path_prefix: str) -> tuple:
index = faiss.read_index(f"{path_prefix}.index")
with open(f"{path_prefix}_texts.pkl", "rb") as f:
texts = pickle.load(f)
return index, texts
Пошук та RAG-відповідь:
def faiss_rag_answer(
question: str,
index: faiss.Index,
texts: list[str],
top_k: int = 5
) -> str:
# Embedding запитання
query_embedding = openai_client.embeddings.create(
model="text-embedding-3-small",
input=question,
).data[0].embedding
query_vector = np.array([query_embedding], dtype=np.float32)
faiss.normalize_L2(query_vector)
# Пошук
distances, indices = index.search(query_vector, top_k)
# Витяг текстів
context_texts = [texts[i] for i in indices[0] if i >= 0]
context = "\n\n---\n\n".join(context_texts)
# Генерація відповіді
response = openai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "Відповідай строго на основі наданого контексту."},
{"role": "user", "content": f"Контекст:\n{context}\n\nЗапитання: {question}"}
],
temperature=0,
)
return response.choices[0].message.content
Процес роботи над RAG-пайплайном
- Аналітика: вивчаємо корпус, вимоги до latency, точності (recall), обсягу оновлень. Обираємо тип індексу.
- Проектування: визначаємо пайплайн — ембендер (OpenAI / локальний), індекс, LLM (GPT-4o-mini / Claude). Опрацьовуємо формат контексту.
- Реалізація: розгортаємо код індексації та пошуку, інтегруємо з існуючим додатком (API / embedded).
- Тестування: заміряємо latency, recall, якість відповідей. Оптимізуємо параметри (M, efSearch, batch size).
- Деплой: контейнеризація (Docker), CI/CD, моніторинг метрик (p99 latency, QPS, утилізація GPU).
Що входить у роботу
- Архітектура пайплайну (схема + документація PDF)
- Код індексації та пошуку (Python, версіонований Git, доступ до репозиторію)
- Конфігурація індексу під ваш корпус (рекомендації щодо HNSW/IVF)
- Інтеграція з LLM (OpenAI, локальні моделі через vLLM)
- Навантажувальне тестування (звіт із метриками)
- Навчання команди (1 сесія до 2 годин)
- Гарантійна підтримка 2 тижні після деплою
Типові помилки при впровадженні FAISS
- Нормалізація не виконана. Без L2-нормалізації inner product не еквівалентний cosine similarity — результати погіршуються на 10–20%.
- Вибір неправильного індексу. IndexFlatL2 на 10M векторів споживає більше 60 ГБ RAM — використовуйте IVFPQ.
- efSearch не налаштований. Для HNSW значення efSearch < 100 знижує recall до 80% — піднімайте до 200–400.
- Ігнорування GPU-пам'яті. Для великих індексів res не поміщається на GPU — переходьте на IVF з квантуванням.
Порівняння типів індексів FAISS
FAISS HNSW забезпечує пошук у 10 разів швидше, ніж IVF при однаковій точності. Таким чином, FAISS індексація для RAG пайплайну забезпечує високошвидкісний семантичний пошук по документах, що дозволяє реалізувати ефективний offline RAG з мінімальними витратами.
| Тип індексу | Точність (recall) | Швидкість (latency) | Пам'ять | Рекомендований розмір корпусу |
|---|---|---|---|---|
| IndexFlatL2 | 100% | ~50 мс для 100K | ~600 МБ (1536 dim) | До 100K |
| IndexIVFFlat | ~95% (на 100 центроїдів) | ~5 мс | ~600 МБ + центроїди | 100K – 10M |
| IndexHNSWFlat | ~98% (efSearch=200) | ~2 мс | ~1.2 ГБ (з графами) | 100K – 10M |
| IndexIVFPQ | ~90% (8x квантування) | ~1 мс | ~75 МБ (стиснення 8x) | >10M |
Терміни та як замовити
Орієнтовні терміни: для корпусу до 500K векторів — 1–2 тижні «під ключ». Для великих обсягів (>10M) — 3–4 тижні з урахуванням оптимізації індексу. Зв'яжіться з нами для оцінки вашого сценарію — ми підберемо конфігурацію та розрахуємо вартість індивідуально. Отримайте консультацію щодо впровадження FAISS у ваш проект. Замовте аудит вашого поточного пайплайну для виявлення вузьких місць.







