mirror of
https://github.com/trustgraph-ai/trustgraph.git
synced 2026-04-26 00:46:22 +02:00
308 lines
17 KiB
Markdown
308 lines
17 KiB
Markdown
|
|
---
|
|||
|
|
layout: default
|
|||
|
|
title: "Управление жизненным циклом векторных хранилищ"
|
|||
|
|
parent: "Russian (Beta)"
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Управление жизненным циклом векторных хранилищ
|
|||
|
|
|
|||
|
|
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
|||
|
|
|
|||
|
|
## Обзор
|
|||
|
|
|
|||
|
|
Этот документ описывает, как TrustGraph управляет коллекциями векторных хранилищ в различных реализациях бэкенда (Qdrant, Pinecone, Milvus). Проект решает проблему поддержки вложений с разными размерностями без жесткой кодировки значений размерностей.
|
|||
|
|
|
|||
|
|
## Описание проблемы
|
|||
|
|
|
|||
|
|
Векторные хранилища требуют указания размерности вложений при создании коллекций/индексов. Однако:
|
|||
|
|
Разные модели вложений генерируют разные размерности (например, 384, 768, 1536).
|
|||
|
|
Размерность неизвестна до генерации первого вложения.
|
|||
|
|
Одна коллекция TrustGraph может получать вложения из нескольких моделей.
|
|||
|
|
Жесткая кодировка размерности (например, 384) приводит к сбоям при использовании других размеров вложений.
|
|||
|
|
|
|||
|
|
## Принципы проектирования
|
|||
|
|
|
|||
|
|
1. **Отложенное создание**: Коллекции создаются по запросу при первой записи, а не во время операций управления коллекциями.
|
|||
|
|
2. **Именование на основе размерности**: Имена коллекций включают размерность вложения в качестве суффикса.
|
|||
|
|
3. **Плавное снижение функциональности**: Запросы к несуществующим коллекциям возвращают пустые результаты, а не ошибки.
|
|||
|
|
4. **Поддержка нескольких размерностей**: Одна логическая коллекция может иметь несколько физических коллекций (по одной для каждой размерности).
|
|||
|
|
|
|||
|
|
## Архитектура
|
|||
|
|
|
|||
|
|
### Соглашение об именовании коллекций
|
|||
|
|
|
|||
|
|
Коллекции векторных хранилищ используют суффиксы, указывающие размерность, для поддержки нескольких размеров вложений:
|
|||
|
|
|
|||
|
|
**Вложения документов:**
|
|||
|
|
Qdrant: `d_{user}_{collection}_{dimension}`
|
|||
|
|
Pinecone: `d-{user}-{collection}-{dimension}`
|
|||
|
|
Milvus: `doc_{user}_{collection}_{dimension}`
|
|||
|
|
|
|||
|
|
**Вложения графов:**
|
|||
|
|
Qdrant: `t_{user}_{collection}_{dimension}`
|
|||
|
|
Pinecone: `t-{user}-{collection}-{dimension}`
|
|||
|
|
Milvus: `entity_{user}_{collection}_{dimension}`
|
|||
|
|
|
|||
|
|
Примеры:
|
|||
|
|
`d_alice_papers_384` - Коллекция статей Алисы с вложениями размерностью 384.
|
|||
|
|
`d_alice_papers_768` - Та же логическая коллекция с вложениями размерностью 768.
|
|||
|
|
`t_bob_knowledge_1536` - Граф знаний Боба с вложениями размерностью 1536.
|
|||
|
|
|
|||
|
|
### Фазы жизненного цикла
|
|||
|
|
|
|||
|
|
#### 1. Запрос на создание коллекции
|
|||
|
|
|
|||
|
|
**Поток запросов:**
|
|||
|
|
```
|
|||
|
|
User/System → Librarian → Storage Management Topic → Vector Stores
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Поведение:**
|
|||
|
|
Библиотекарь отправляет запросы `create-collection` всем хранилищам данных.
|
|||
|
|
Процессоры векторных хранилищ подтверждают запрос, но **не создают физические коллекции**.
|
|||
|
|
Ответ возвращается немедленно с сообщением об успехе.
|
|||
|
|
Фактическое создание коллекции откладывается до первой записи.
|
|||
|
|
|
|||
|
|
**Обоснование:**
|
|||
|
|
Размерность неизвестна на момент создания.
|
|||
|
|
Предотвращает создание коллекций с неправильными размерами.
|
|||
|
|
Упрощает логику управления коллекциями.
|
|||
|
|
|
|||
|
|
#### 2. Операции записи (отложенное создание)
|
|||
|
|
|
|||
|
|
**Поток записи:**
|
|||
|
|
```
|
|||
|
|
Data → Storage Processor → Check Collection → Create if Needed → Insert
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Поведение:**
|
|||
|
|
1. Извлечь размерность вложения из вектора: `dim = len(vector)`
|
|||
|
|
2. Сформировать имя коллекции с суффиксом, указывающим на размерность.
|
|||
|
|
3. Проверить, существует ли коллекция с указанной размерностью.
|
|||
|
|
4. Если коллекция не существует:
|
|||
|
|
Создать коллекцию с правильной размерностью.
|
|||
|
|
Записать в лог: `"Lazily creating collection {name} with dimension {dim}"`
|
|||
|
|
5. Вставить вложение в коллекцию, специфичную для данной размерности.
|
|||
|
|
|
|||
|
|
**Пример сценария:**
|
|||
|
|
```
|
|||
|
|
1. User creates collection "papers"
|
|||
|
|
→ No physical collections created yet
|
|||
|
|
|
|||
|
|
2. First document with 384-dim embedding arrives
|
|||
|
|
→ Creates d_user_papers_384
|
|||
|
|
→ Inserts data
|
|||
|
|
|
|||
|
|
3. Second document with 768-dim embedding arrives
|
|||
|
|
→ Creates d_user_papers_768
|
|||
|
|
→ Inserts data
|
|||
|
|
|
|||
|
|
Result: Two physical collections for one logical collection
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3. Операции запросов
|
|||
|
|
|
|||
|
|
**Поток запросов:**
|
|||
|
|
```
|
|||
|
|
Query Vector → Determine Dimension → Check Collection → Search or Return Empty
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Поведение:**
|
|||
|
|
1. Извлечение размерности из вектора запроса: `dim = len(vector)`
|
|||
|
|
2. Формирование имени коллекции с суффиксом, указывающим размерность.
|
|||
|
|
3. Проверка наличия коллекции.
|
|||
|
|
4. Если коллекция существует:
|
|||
|
|
Выполнение поиска по схожести.
|
|||
|
|
Возврат результатов.
|
|||
|
|
5. Если коллекция не существует:
|
|||
|
|
Запись в журнал: `"Collection {name} does not exist, returning empty results"`
|
|||
|
|
Возврат пустого списка (без возникновения ошибки).
|
|||
|
|
|
|||
|
|
**Несколько размерностей в одном запросе:**
|
|||
|
|
Если запрос содержит векторы разных размерностей.
|
|||
|
|
Для каждой размерности выполняется поиск в соответствующей коллекции.
|
|||
|
|
Результаты объединяются.
|
|||
|
|
Отсутствующие коллекции пропускаются (не рассматриваются как ошибки).
|
|||
|
|
|
|||
|
|
**Обоснование:**
|
|||
|
|
Запрос к пустой коллекции является допустимым сценарием использования.
|
|||
|
|
Возврат пустых результатов является семантически правильным.
|
|||
|
|
Предотвращает ошибки при запуске системы или до загрузки данных.
|
|||
|
|
|
|||
|
|
#### 4. Удаление коллекции
|
|||
|
|
|
|||
|
|
**Процесс удаления:**
|
|||
|
|
```
|
|||
|
|
Delete Request → List All Collections → Filter by Prefix → Delete All Matches
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Поведение:**
|
|||
|
|
1. Создание префиксного шаблона: `d_{user}_{collection}_` (обратите внимание на завершающий символ подчеркивания)
|
|||
|
|
2. Перечисление всех коллекций в векторной базе данных.
|
|||
|
|
3. Фильтрация коллекций, соответствующих префиксу.
|
|||
|
|
4. Удаление всех соответствующих коллекций.
|
|||
|
|
5. Запись каждого удаления в журнал: `"Deleted collection {name}"`
|
|||
|
|
6. Итоговый журнал: `"Deleted {count} collection(s) for {user}/{collection}"`
|
|||
|
|
|
|||
|
|
**Пример:**
|
|||
|
|
```
|
|||
|
|
Collections in store:
|
|||
|
|
- d_alice_papers_384
|
|||
|
|
- d_alice_papers_768
|
|||
|
|
- d_alice_reports_384
|
|||
|
|
- d_bob_papers_384
|
|||
|
|
|
|||
|
|
Delete "papers" for alice:
|
|||
|
|
→ Deletes: d_alice_papers_384, d_alice_papers_768
|
|||
|
|
→ Keeps: d_alice_reports_384, d_bob_papers_384
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Обоснование:**
|
|||
|
|
Обеспечивает полную очистку всех вариантов измерений.
|
|||
|
|
Сопоставление с образцом предотвращает случайное удаление несвязанных коллекций.
|
|||
|
|
Атомарная операция с точки зрения пользователя (все измерения удаляются вместе).
|
|||
|
|
|
|||
|
|
## Поведенческие характеристики
|
|||
|
|
|
|||
|
|
### Нормальная работа
|
|||
|
|
|
|||
|
|
**Создание коллекции:**
|
|||
|
|
✓ Немедленно возвращает успешный результат.
|
|||
|
|
✓ Не выделяется физическое хранилище.
|
|||
|
|
✓ Быстрая операция (без операций ввода-вывода на стороне сервера).
|
|||
|
|
|
|||
|
|
**Первая запись:**
|
|||
|
|
✓ Создает коллекцию с правильным измерением.
|
|||
|
|
✓ Немного медленнее из-за накладных расходов на создание коллекции.
|
|||
|
|
✓ Последующие записи в то же измерение выполняются быстро.
|
|||
|
|
|
|||
|
|
**Запросы до любых записей:**
|
|||
|
|
✓ Возвращает пустые результаты.
|
|||
|
|
✓ Без ошибок или исключений.
|
|||
|
|
✓ Система остается стабильной.
|
|||
|
|
|
|||
|
|
**Смешанные записи измерений:**
|
|||
|
|
✓ Автоматически создает отдельные коллекции для каждого измерения.
|
|||
|
|
✓ Каждое измерение изолировано в своей коллекции.
|
|||
|
|
✓ Отсутствуют конфликты измерений или ошибки схемы.
|
|||
|
|
|
|||
|
|
**Удаление коллекции:**
|
|||
|
|
✓ Удаляет все варианты измерений.
|
|||
|
|
✓ Полная очистка.
|
|||
|
|
✓ Отсутствуют "осиротевшие" коллекции.
|
|||
|
|
|
|||
|
|
### Крайние случаи
|
|||
|
|
|
|||
|
|
**Несколько моделей встраивания:**
|
|||
|
|
```
|
|||
|
|
Scenario: User switches from model A (384-dim) to model B (768-dim)
|
|||
|
|
Behavior:
|
|||
|
|
- Both dimensions coexist in separate collections
|
|||
|
|
- Old data (384-dim) remains queryable with 384-dim vectors
|
|||
|
|
- New data (768-dim) queryable with 768-dim vectors
|
|||
|
|
- Cross-dimension queries return results only for matching dimension
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Одновременные первые записи:**
|
|||
|
|
```
|
|||
|
|
Scenario: Multiple processes write to same collection simultaneously
|
|||
|
|
Behavior:
|
|||
|
|
- Each process checks for existence before creating
|
|||
|
|
- Most vector stores handle concurrent creation gracefully
|
|||
|
|
- If race condition occurs, second create is typically idempotent
|
|||
|
|
- Final state: Collection exists and both writes succeed
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Миграция измерений:**
|
|||
|
|
```
|
|||
|
|
Scenario: User wants to migrate from 384-dim to 768-dim embeddings
|
|||
|
|
Behavior:
|
|||
|
|
- No automatic migration
|
|||
|
|
- Old collection (384-dim) persists
|
|||
|
|
- New collection (768-dim) created on first new write
|
|||
|
|
- Both dimensions remain accessible
|
|||
|
|
- Manual deletion of old dimension collections possible
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Запросы к пустой коллекции:**
|
|||
|
|
```
|
|||
|
|
Scenario: Query a collection that has never received data
|
|||
|
|
Behavior:
|
|||
|
|
- Collection doesn't exist (never created)
|
|||
|
|
- Query returns empty list
|
|||
|
|
- No error state
|
|||
|
|
- System logs: "Collection does not exist, returning empty results"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Заметки об реализации
|
|||
|
|
|
|||
|
|
### Особенности используемого хранилища данных
|
|||
|
|
|
|||
|
|
**Qdrant:**
|
|||
|
|
Использует `collection_exists()` для проверок существования
|
|||
|
|
Использует `get_collections()` для перечисления при удалении
|
|||
|
|
Создание коллекции требует `VectorParams(size=dim, distance=Distance.COSINE)`
|
|||
|
|
|
|||
|
|
**Pinecone:**
|
|||
|
|
Использует `has_index()` для проверок существования
|
|||
|
|
Использует `list_indexes()` для перечисления при удалении
|
|||
|
|
Создание индекса требует ожидания статуса "ready"
|
|||
|
|
Serverless режим конфигурируется с указанием облака/региона
|
|||
|
|
|
|||
|
|
**Milvus:**
|
|||
|
|
Прямые классы (`DocVectors`, `EntityVectors`) управляют жизненным циклом
|
|||
|
|
Внутренний кэш `self.collections[(dim, user, collection)]` для повышения производительности
|
|||
|
|
Имена коллекций очищаются (только буквенно-цифровые символы и подчеркивание)
|
|||
|
|
Поддерживает схему с автоматически увеличивающимися идентификаторами
|
|||
|
|
|
|||
|
|
### Вопросы производительности
|
|||
|
|
|
|||
|
|
**Задержка при первой записи:**
|
|||
|
|
Дополнительные накладные расходы, связанные с созданием коллекции
|
|||
|
|
Qdrant: ~100-500 мс
|
|||
|
|
Pinecone: ~10-30 секунд (подготовка serverless режима)
|
|||
|
|
Milvus: ~500-2000 мс (включая индексацию)
|
|||
|
|
|
|||
|
|
**Производительность запросов:**
|
|||
|
|
Проверка существования добавляет минимальные накладные расходы (~1-10 мс)
|
|||
|
|
Отсутствие влияния на производительность после создания коллекции
|
|||
|
|
Каждая коллекция, соответствующая определенной размерности, оптимизируется независимо
|
|||
|
|
|
|||
|
|
**Накладные расходы на хранение:**
|
|||
|
|
Минимальный объем метаданных на коллекцию
|
|||
|
|
Основные накладные расходы связаны с хранением данных для каждой размерности
|
|||
|
|
Компромисс: объем хранимых данных против гибкости размерностей
|
|||
|
|
|
|||
|
|
## Будущие улучшения
|
|||
|
|
|
|||
|
|
**Автоматическая консолидация размерностей:**
|
|||
|
|
Можно добавить фоновый процесс для выявления и объединения неиспользуемых вариантов размерностей
|
|||
|
|
Это потребует повторной встраиваемости или уменьшения размерности
|
|||
|
|
|
|||
|
|
**Обнаружение размерностей:**
|
|||
|
|
Можно предоставить API для перечисления всех используемых размерностей для коллекции
|
|||
|
|
Полезно для администрирования и мониторинга
|
|||
|
|
|
|||
|
|
**Предпочтительная размерность по умолчанию:**
|
|||
|
|
Можно отслеживать "основную" размерность для каждой коллекции
|
|||
|
|
Использовать для запросов, когда контекст размерности недоступен
|
|||
|
|
|
|||
|
|
**Квоты на хранение:**
|
|||
|
|
Возможно, потребуются ограничения на количество размерностей на коллекцию
|
|||
|
|
Предотвращение чрезмерного количества вариантов размерностей
|
|||
|
|
|
|||
|
|
## Примечания по миграции
|
|||
|
|
|
|||
|
|
**Из системы с суффиксом размерности:**
|
|||
|
|
Старые коллекции: `d_{user}_{collection}` (без суффикса размерности)
|
|||
|
|
Новые коллекции: `d_{user}_{collection}_{dim}` (с суффиксом размерности)
|
|||
|
|
Отсутствует автоматическая миграция - старые коллекции остаются доступными
|
|||
|
|
Рассмотрите возможность использования скрипта для ручной миграции, если это необходимо
|
|||
|
|
Можно использовать обе схемы именования одновременно
|
|||
|
|
|
|||
|
|
## Ссылки
|
|||
|
|
|
|||
|
|
Управление коллекциями: `docs/tech-specs/collection-management.md`
|
|||
|
|
Схема хранения: `trustgraph-base/trustgraph/schema/services/storage.py`
|
|||
|
|
Сервис Librarian: `trustgraph-flow/trustgraph/librarian/service.py`
|