Настроить векторную базу для RAG обычно сводится к четырем решениям: выбрать бэкенд, зафиксировать модель эмбеддингов и размерность, правильно нарезать документы на чанки и проверить реальный retrieval на контрольных запросах. Для удаленного управляемого сервиса чаще выбирают Pinecone, для локальной разработки и self-hosted сценариев — Chroma. Такой подход плохо подходит там, где важнее строгие SQL-запросы, транзакционность, точный keyword search без семантики, сложные join-операции или есть запрет на передачу эмбеддингов во внешний сервис.
Короткий ответ
Если нужен быстрый старт без поддержки собственной инфраструктуры, берите Pinecone. Если важны локальный запуск, низкий порог входа и возможность держать все данные рядом с приложением, начните с Chroma. В обоих случаях нельзя смешивать разные модели эмбеддингов в одном индексе, менять размерность после создания и рассчитывать, что большие неочищенные документы будут хорошо искаться без чанкинга.
| Сценарий | Pinecone | Chroma | Что выбрать |
|---|---|---|---|
| Локальная разработка и прототип | Избыточно, если не нужен удаленный сервис | Простой локальный запуск и быстрые итерации | Chroma |
| Продакшен без своей команды инфраструктуры | Управляемый сервис, отдельные индексы и namespaces | Потребует собственной эксплуатации | Pinecone |
| Изолированная среда или данные нельзя выносить наружу | Часто не подходит по политике данных | Можно держать локально или в своем контуре | Chroma |
| Нужно быстро проверить качество retrieval до релиза | Подходит, но сложнее и дороже по времени запуска | Достаточно для тестов и первых замеров | Chroma |
| Нужна единая удаленная точка доступа для нескольких сервисов | Подходит лучше | Возможен, но требует отдельной схемы развертывания | Pinecone |
Критерии выбора простые: где будут храниться данные, кто отвечает за эксплуатацию, нужна ли удаленная многопользовательская точка доступа, как часто вы переиндексируете корпус и готовы ли вы держать отдельный сервис рядом с приложением.
- Одна модель эмбеддингов на индекс: документы и запросы кодируются одной и той же моделью.
- Одна размерность: размер вектора должен совпадать с параметром индекса или коллекции.
- Одна метрика: чаще всего
cosine; ее нужно выбрать до загрузки данных. - Проверка retrieval обязательна: успешная загрузка векторов еще не означает полезный поиск.
Что понадобится
- Python 3.10+ и минимальная среда для скриптов индексации.
- Выбранная модель эмбеддингов. В примерах ниже используется локальная модель размерности
384. Если вы возьмете другую модель, изменится размерность индекса. - Набор документов, который уже очищен от мусора: навигации, дублей, служебных блоков, HTML-шумов.
- Стратегия чанкинга: разумный размер чанка, перекрытие, стабильные идентификаторы вида
doc-id#chunk-id. - Набор контрольных запросов с ожидаемыми релевантными документами. Без него нельзя понять, работает ли база по смыслу.
- Выбор бэкенда: аккаунт Pinecone или локально установленный Chroma.
pip install pinecone chromadb sentence-transformers
Официальная документация: Pinecone, Chroma.
Что стоит решить до первой загрузки
- Метрика: обычно
cosineдля текстовых эмбеддингов. - Размер чанка: для документации и статей часто подходят 300–800 токенов; для коротких карточек — меньше.
- Перекрытие чанков: обычно 10–20% текста, чтобы не рвать смысл на границах.
- Метаданные: источник, версия, язык, раздел, дата обновления, права доступа.
- Политика обновления: полная переиндексация или инкрементальная загрузка.
- Политика хранения данных: можно ли отправлять эмбеддинги и метаданные во внешний сервис.
Пошаговый план
1. Зафиксируйте схему индекса
Сначала выберите одну модель эмбеддингов и посмотрите ее размерность. Именно эта размерность задается при создании индекса в Pinecone или используется как фактический контракт коллекции в Chroma. Если потом заменить модель на другую размерность, придется переиндексировать весь корпус.
- Модель: одна для документов и запросов.
- Размерность: например,
384для компактной локальной модели. - Метрика: обычно
cosine. - Идентификаторы: стабильные и детерминированные, чтобы повторный запуск не плодил дубли.
2. Подготовьте документы и чанки
Не загружайте в векторную базу целые PDF или HTML-страницы одним куском. Сначала извлеките текст, удалите повторяющиеся блоки и разрежьте документы на смысловые чанки. Хорошая база строится не на количестве векторов, а на качестве кусков текста.
- Очищайте шаблонный шум: меню, футеры, юридические повторы.
- Не делайте слишком большие чанки: они размывают смысл и снижают точность поиска.
- Не делайте слишком маленькие чанки: ответ теряет контекст.
- Сохраняйте исходный текст чанка или ссылку на него, чтобы потом собрать ответ и показать источник.
3. Сгенерируйте эмбеддинги
Ниже минимальный пример с локальной моделью. Нормализация полезна, если вы работаете с косинусной близостью и хотите устойчивое поведение при сравнении.
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('all-MiniLM-L6-v2')
chunks = [
'Сброс пароля доступен в разделе Настройки безопасности.',
'Токен восстановления действует 15 минут.'
]
vectors = model.encode(chunks, normalize_embeddings=True).tolist()
Если вы используете другую модель, замените и код генерации, и размерность индекса. Частая ошибка — оставить старую размерность, а потом получить отказ при записи.
4. Создайте индекс в Pinecone
Pinecone полезен там, где нужен удаленный управляемый сервис и вы не хотите отдельно поднимать свою векторную инфраструктуру. Создайте индекс заранее, задав правильную размерность и метрику.
import os
from pinecone import Pinecone, ServerlessSpec
pc = Pinecone(api_key=os.environ['PINECONE_API_KEY'])
index_name = 'docs'
if not pc.has_index(index_name):
pc.create_index(
name=index_name,
dimension=384,
metric='cosine',
spec=ServerlessSpec(cloud='aws', region='us-east-1')
)
index = pc.Index(index_name)
index.upsert(
vectors=[
{
'id': 'doc-1#0',
'values': vectors[0],
'metadata': {'source': 'manual', 'chunk': 0, 'version': 1}
}
],
namespace='kb'
)
Практические замечания для Pinecone:
- Namespaces удобны для разделения корпусов, окружений или тенантов.
- Метаданные должны быть компактными: не храните в них большие тексты без причины.
- Доступ и политика данных должны быть согласованы заранее, если документы чувствительные.
5. Создайте коллекцию в Chroma
Chroma удобен для локальных стендов, быстрых экспериментов и случаев, когда векторы должны храниться рядом с приложением. Для простого старта достаточно persistent-клиента и одной коллекции.
import chromadb
client = chromadb.PersistentClient(path='./chroma_data')
collection = client.get_or_create_collection(
name='docs',
metadata={'hnsw:space': 'cosine'}
)
collection.add(
ids=['doc-1#0'],
documents=[chunks[0]],
metadatas=[{'source': 'manual', 'chunk': 0, 'version': 1}],
embeddings=[vectors[0]]
)
Практические замечания для Chroma:
- Путь хранения должен быть стабильным и попадать в резервное копирование, если данные важны.
- Коллекция должна соответствовать одной схеме эмбеддингов. Не смешивайте в одной коллекции разные модели.
- Локальный запуск удобен, но ответственность за обновления и доступ лежит на вас.
6. Выполните тестовый поиск
После записи хотя бы части корпуса сразу проверяйте retrieval. Не ждите полной индексации, чтобы увидеть базовую проблему с релевантностью.
query = 'как сбросить пароль'
query_vec = model.encode([query], normalize_embeddings=True).tolist()[0]
Pinecone:
res = index.query(vector=query_vec, top_k=5, include_metadata=True, namespace='kb')
Chroma:
res = collection.query(query_embeddings=[query_vec], n_results=5)
Смотрите не только на наличие результатов, но и на их смысл: попадает ли нужный раздел в первые позиции, нет ли повторов одного и того же документа, достаточно ли контекста в найденном чанке для ответа LLM.
7. Настройте обновления, удаление и повторную индексацию
Без этого векторная база быстро теряет ценность: документы меняются, а старые чанки остаются в поиске.
- Используйте стабильные ID, чтобы повторный запуск обновлял записи, а не создавал дубли.
- Храните версию документа в метаданных.
- Удаляйте старые чанки перед записью новой версии документа, если логика не гарантирует безопасный upsert.
- Разделяйте dev и prod по индексам, namespaces или коллекциям.
- Планируйте полную переиндексацию при смене модели эмбеддингов, схемы чанкинга или очистки текста.
Типичные ошибки
- Смена модели без переиндексации. Старые и новые векторы оказываются в разном пространстве, поиск становится непредсказуемым.
- Неверная размерность. Индекс создан под одно число измерений, а модель выдает другое.
- Слишком крупные чанки. Внутри одного вектора смешиваются несколько тем, и релевантность падает.
- Отсутствие перекрытия. Смысл рвется на стыке чанков, и нужный ответ не находится.
- Дубли при повторной загрузке. Если ID генерируются случайно, корпус разрастается мусором.
- Нет контрольных запросов. Формально все работает, но retrieval не решает вашу задачу.
- Слишком богатые метаданные. Большие JSON-поля утяжеляют запись и не дают пользы поиску.
- Игнорирование политики данных. Для внешнего managed-сервиса нужно заранее проверить, можно ли отправлять туда ваши эмбеддинги и метаданные.
- Ожидание, что векторная база заменит полнотекстовый поиск. Для кодов ошибок, артикулов, названий функций и точных фраз часто нужен гибридный поиск.
Как проверить результат
| Проверка | Что сделать | Нормальный результат | Если плохо |
|---|---|---|---|
| Структурная | Сверить число чанков до и после загрузки | Количество записей совпадает с ожиданием | Проверить генерацию ID и ошибки batch-загрузки |
| Семантическая | Прогнать 20–50 контрольных запросов | Нужные документы попадают в top-3 или top-5 | Пересмотреть чанкинг, модель и метаданные |
| Дубликаты | Проверить выдачу на повторы одного документа | Повторы минимальны | Добавить дедупликацию и стабилизировать ID |
| Обновления | Изменить документ и переиндексировать его | В выдаче видна новая версия | Проверить логику delete/upsert и версионность |
| Фильтрация | Ограничить поиск по разделу, языку или тенанту | Посторонние документы не попадают в ответ | Проверить метаданные и схему namespace/collection |
Минимально полезная проверка — набор реальных пользовательских запросов с ручной оценкой релевантности. Если top-результаты выглядят правдоподобно, но LLM все равно отвечает плохо, проблема может быть уже не в базе, а в промпте, ранжировании, обрезке контекста или сборке ответа.
FAQ
Можно ли начать с Chroma, а потом перейти на Pinecone?
Да. Это нормальный путь: локально отлаживаете чанкинг и retrieval в Chroma, затем переносите ту же схему в Pinecone. Важно не менять модель эмбеддингов, формат ID и метаданные без необходимости. Если меняете — делайте полную переиндексацию.
Нужно ли хранить текст чанков в самой векторной базе?
Для простого RAG — обычно да, потому что так проще вернуть найденный контекст сразу из retrieval-слоя. Для больших систем можно хранить только ID и метаданные, а текст держать отдельно в документном хранилище. Но тогда усложняется сборка ответа и диагностика.
Можно ли менять модель эмбеддингов без пересоздания индекса?
Практически нет. Даже если размерность совпала, пространство эмбеддингов уже другое. Корректный путь — создать новый индекс или коллекцию и переиндексировать весь корпус.
Когда Pinecone и Chroma не лучший выбор?
Когда основной поиск строится на точных совпадениях, артикуле, номере ошибки, названии поля или фразы; когда нужны сложные транзакции и join-операции; когда объем данных мал и обычный полнотекстовый поиск решает задачу проще; когда есть жесткий запрет на внешний managed-сервис, а инфраструктуру поднимать некому.
Нужен ли гибридный поиск?
Часто да. Векторный поиск хорошо находит смысловые совпадения, но слабее работает на кодах, идентификаторах и редких точных терминах. Если у вас база знаний по API, каталог товаров или техподдержка с номерами ошибок, гибридный поиск обычно надежнее чисто векторного.
Какой размер чанка выбрать?
Начните с диапазона, в котором один чанк содержит законченную мысль, но не несколько разных тем сразу. Для документации это часто 300–800 токенов с перекрытием 10–20%. Дальше ориентируйтесь на контрольные запросы: если в выдаче много размазанного контекста, чанки уменьшайте; если ответ не хватает собрать из одного-двух чанков, увеличивайте.