COMRAD404 / HOWTO

Как настроить векторную базу: Pinecone и Chroma

Практическая настройка Pinecone и Chroma для RAG: выбор бэкенда, размерность, индексация чанков, проверка retrieval и типичные ошибки.

Настроить векторную базу для 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 или коллекциям.
  • Планируйте полную переиндексацию при смене модели эмбеддингов, схемы чанкинга или очистки текста.

Типичные ошибки

  1. Смена модели без переиндексации. Старые и новые векторы оказываются в разном пространстве, поиск становится непредсказуемым.
  2. Неверная размерность. Индекс создан под одно число измерений, а модель выдает другое.
  3. Слишком крупные чанки. Внутри одного вектора смешиваются несколько тем, и релевантность падает.
  4. Отсутствие перекрытия. Смысл рвется на стыке чанков, и нужный ответ не находится.
  5. Дубли при повторной загрузке. Если ID генерируются случайно, корпус разрастается мусором.
  6. Нет контрольных запросов. Формально все работает, но retrieval не решает вашу задачу.
  7. Слишком богатые метаданные. Большие JSON-поля утяжеляют запись и не дают пользы поиску.
  8. Игнорирование политики данных. Для внешнего managed-сервиса нужно заранее проверить, можно ли отправлять туда ваши эмбеддинги и метаданные.
  9. Ожидание, что векторная база заменит полнотекстовый поиск. Для кодов ошибок, артикулов, названий функций и точных фраз часто нужен гибридный поиск.

Как проверить результат

Проверка Что сделать Нормальный результат Если плохо
Структурная Сверить число чанков до и после загрузки Количество записей совпадает с ожиданием Проверить генерацию 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%. Дальше ориентируйтесь на контрольные запросы: если в выдаче много размазанного контекста, чанки уменьшайте; если ответ не хватает собрать из одного-двух чанков, увеличивайте.

Читайте также

LINKS