Ваш ИИ-помощник может использовать устаревшие данные. Этот инструмент с открытым исходным кодом хочет это исправить
by LJ 12 апреля 2025
Слишком длинно; не читал
Узнайте о параллельных обновлениях, рисках утечки данных и лучших практиках для обеспечения надежных, актуальных индексов, используя подход CocoIndex, основанный на данных.
Проблема параллельных обновлений
В отличие от создания однопроцессной логики преобразования в памяти, индексационный конвейер сталкивается с дополнительными сложностями в двух аспектах, чтобы поддерживать согласованность данных:
-
Во времени, это длительный процесс, т.е. его выполнение может охватывать несколько процессов. Например, раннее выполнение может быть прервано SIGTERM, сбоем при записи в целевое хранилище или перезагрузкой. Когда процесс перезапускается позже, он должен подхватить существующие состояния и продолжить обновление целевого хранилища до желаемого состояния. Это как утомительно, так и подвержено ошибкам: например, если данные из источника обрабатываются частично, и они обновляются до того, как перезапущенный конвейер начнет обрабатывать их снова, как мы можем убедиться, что состояния, полученные из старой версии, корректно очищены?
-
В пространственном плане выполнение происходит параллельно, иногда распределено на несколько машин для больших нагрузок. Это вызывает проблему, связанную с обработкой данных не в том порядке. Рассмотрим ситуацию, когда ваши данные источника обновляются быстро:
- Версия 1 (V1) существует в системе
- Версия 2 (V2) и версия 3 (V3) приходят в течение одной секунды друг за другом
- V2 обрабатывается дольше, чем V3. Без должного управления, вы можете получить данные V2 в вашем индексе, даже если V3 является последней версией – фактически вернувшись к устаревшим данным.
Общие проблемы и недостатки
Риски утечки данных
Несогласованность данных в индексирующих системах может привести к нескольким критическим проблемам:
Целостность системы
- Устаревшие данные сохраняются в индексах, несмотря на обновления источника
- Несогласованные состояния в разных системах хранения
- Смешанные версии одной и той же записи источника сосуществуют в индексе
Безопасность и соблюдение нормативных требований
- Удаленная конфиденциальная информация остается доступной через поисковые интерфейсы
- Устаревшие личные данные нарушают требования конфиденциальности (например, GDPR)
- Несоблюдение нормативных требований из-за неправильного хранения записей
Надежность ИИ-систем
- Системы RAG включают устаревшую информацию в ответы
- Семантический поиск выводит устаревший или отозванный контент
- Агенты ИИ принимают решения на основе устаревших данных
Бизнес-операции
- Приложения, ориентированные на клиентов, показывают неверную информацию
- Потеря доверия из-за несогласованного представления данных
- Финансовые потери из-за устаревшей информации о ценах или товарных деталях
Подходы к поддержанию согласованности данных
1. Отслеживание сопоставления ключей от источника к цели
Если все ваши системы управления состоянием и хранения находятся в одной транзакционной системе (например, PostgreSQL), вы можете использовать транзакции базы данных для обеспечения согласованности. Однако это часто не происходит в реальных сценариях. Например, вы можете использовать внутреннее хранилище (например, PostgreSQL) для отслеживания метаданных по источнику и внешнее векторное хранилище (например, Pinecone или Milvus) для хранения векторных встраиваний.
- Нам необходимо отслеживать все ключи в целевых векторных хранилищах, полученных из каждого исходного ключа, во внутреннем хранилище. Это необходимо, когда старая версия данных источника обновляется или удаляется: нам нужно найти ранее полученные ключи и удалить их, если они больше не существуют в новой версии после обработки.
- Однако внутреннее хранилище не является транзакционным по отношению к внешнему векторному хранилищу, так как это две независимые системы хранения. Так что, если процесс завершится ненормально посреди, состояния в двух системах окажутся несогласованными.
Поэтому нам необходимо тщательно спроектировать порядок записей во время коммита, чтобы избежать утечки данных, даже когда процесс выполнен только частично:
- Добавить новые целевые ключи во внутреннее хранилище
- Записать в целевое хранилище
- Создать новые записи
- Удалить старые записи. Обратите внимание, что для любого целевого хранилища, которое поддерживает атомарную запись, это позволяет всем обновлениям, происходящим от одного и того же исходного ключа, записываться атомарно. Это позволяет избежать смешанных версий данных во время запроса.
- Удалить больше не существующие целевые ключи из внутреннего хранилища
Это обеспечивает инвариант ключа: ключи, отслеживаемые во внутреннем хранилище, всегда являются надмножеством тех, которые действительно существуют в целевом хранилище. Это гарантирует, что все данные в целевом хранилище всегда отслеживаются, чтобы не произошла утечка.
2. Порядковое ведение учета
Порядковые номера — это уникальные идентификаторы, которые устанавливают строгий порядок обновлений данных в вашем конвейере. Они помогают вести учет последовательности и времени изменений для обеспечения согласованности. Обычные примеры включают:
- Метки времени (например, 2024-01-06T12:34:56Z) – точный временной порядок
- Номера версий (например, v1.2.3, 20240106.1) – последовательная нумерация
Ведите учет порядковых номеров с осторожностью на двух ключевых этапах:
- Во время внедрения: зафиксируйте и сохраните исходный порядковый номер (например, метка времени или версия) из оригинальных данных
- Во время коммита: проверьте исходный порядковый номер, чтобы предотвратить перезапись новых версий старыми
Ведение учета порядковых номеров происходит на Этапе 1, который отклоняет коммиты в неправильном порядке – они не вызовут никаких обновлений на Этапе 1, и Этапы 2 и 3 вообще не будут выполнены.
3. Назначение уникального ключа с учетом версий с мягким удалением
Когда несколько процессов происходят одновременно над одним и тем же исходным ключом, обновления, записываемые в целевое хранилище, могут происходить не в том порядке, что приводит к перезаписи новых результатов старыми версиями.
Чтобы этого избежать, нам нужно:
- Для данных в целевом хранилище убедиться, что ключи уникальны даже среди разных версий.
- Использовать мягкое удаление в целевом хранилище, т.е. удаленные версии представлены строкой с установленным полем
deleted
.
Специфически:
- В транзакции на Этапе 1 мы устанавливаем полный обзор всех полученных ключей для текущего исходного ключа: собираем существующие ключи и генерируем новые ключи.
- На Этапе 2 мы выполняем UPSERT как для новых, так и для удаленных версий – единственное отличие в том, что для удаленных версий устанавливается поле
deleted
, а для новых версий оно остается без изменений. - Во время времени запроса мы отфильтровываем все записи, в которых установлено поле
deleted
.
Кроме того, нам нужен офлайн процесс сборки мусора для сбора строк в целевом хранилище с установленным полем deleted
. Из-за этого поле deleted
может быть временной меткой времени удаления, поэтому мы можем решить, когда освободить конкретную версию на его основе.
Как мы решили эти проблемы в CocoIndex
Обсуждения выше охватывают лишь часть сложности построения и поддержки долгосрочных или распределенных индексационных конвейеров. Есть и другие дополнительные сложности, по сравнению с построением однопроцессной логики преобразования в памяти, такие как:
- CRUD через разные API
- Управление историческими состояниями по частям
- Повторное использование существующих вычислений
- Миграция данных при изменениях в логике обработки
Фреймворк CocoIndex направлен на решение этих сложностей, чтобы пользователи могли сосредоточиться на чистых преобразованиях:
-
Пользователи пишут преобразования как чистые функции
- Вывод зависит только от входных данных
- Без побочных эффектов или скрытых состояний
- Легко понимать и поддерживать
-
Фреймворк обрабатывает:
- Управление результатами предыдущих вычислений
- Инкрементальная обработка
- Управление состоянием
- Согласованность данных
- Обновление данных при изменениях в логике обработки
Предоставляя парадигму программирования, основанную на данных, CocoIndex позволяет разработчикам сосредоточиться на своей основной бизнес-логике, обеспечивая при этом согласованность и актуальность данных.
Если вам нравится наша работа, пожалуйста, поддержите нас – 🥥 Cocoindex на Github с помощью звезды. Огромное спасибо с теплым кокосовым объятием 🥥🤗.