Назад в блог
RAG Systems

Обновление индекса RAG: ingestion, версии и удаление данных

Надёжный retrieval начинается с versioned контракта source-to-index

Idempotent ingestion, staged promotion, access-aware removal и reconciliation

Авторский INDEX-UPDATE-8 workflow с pseudocode, failure modes и acceptance gates
обновление индекса RAG, ingestion pipeline, версии RAG, удаление данных, RAG architecture и INDEX-UPDATE-8
ТемаVersioned source-to-index convergence
ФокусINDEX-UPDATE-8
СтатусPUBLISHED / 2026-08-31
Контролируемый pipeline проводит исходные документы через versioned chunks, RAG index и gate удаления данных
Контролируемый pipeline проводит исходные документы через versioned chunks, RAG index и gate удаления данных
TERMINAL_PREVIEW.LOG
$ update rag-index --contract INDEX-UPDATE-8
> receive: source event / version / scope
> stage: extract / normalize / chunk / write
> verify: hash / count / access / retrieval
> promote: current / retry / quarantine / remove
> reconcile: source registry / index receipt
Разбор

Индекс RAG — не статичная база, которую один раз собрали для демо. Это проекция исходных документов в конкретный момент. Когда меняется policy, исправляется источник, отзывается доступ или документ нужно удалить, retrieval-слой обязан прийти к новому состоянию без смешивания старых и новых evidence.

Этот материал отвечает на узкий технический запрос «обновление индекса RAG»: ingestion-контракты, версии, удаление, failure modes и production-проверки. Более широкую продуктовую задачу покрывает страница RAG-систем. Для архитектурного ревью команда может начать с AI engineering brief; статья даёт критерии реализации, а не заменяет коммерческую landing page.

Начните с контракта source of truth

Обновление индекса должно начинаться с authoritative source event, а не с изменённого embedding. У source record нужны стабильный sourceId, tenant или access scope, origin, lifecycle, content version, hash, timestamps и ссылка, которую может открыть человек. Каждый derived chunk получает детерминированный ID и сохраняет source version и access attributes, которые сделали его eligible.

Полезный вопрос — не «принял ли vector store upsert?», а «может ли запрос увидеть только нужную current и разрешённую версию source?». Тогда ingestion становится задачей reconciliation: source registry объявляет desired state, workers приводят индекс к нему, а verifier доказывает результат.

text
SOURCE CHANGE
  -> validate source и access attributes
  -> assign immutable sourceVersion + content hash
  -> create idempotent ingestion job
  -> extract / normalize / chunk с pinned configuration
  -> write versioned candidates и retrieval filters
  -> verify count, version, access и citations
  -> promote current | retry | quarantine | remove

Не используйте имя файла, время upload или порядок записей vector store как identity. Эти поля легко меняются и делают retry либо частичный rollback неоднозначными. Детерминированный ключ chunk, например sourceId:version:chunkOrdinal:chunkerVersion, даёт практическую границу восстановления.

Архитектура versioned ingestion

Набросок INDEX-UPDATE-8 сохраняет видимыми границы ответственности. Это архитектурный паттерн, а не предписание конкретного вендора.

КомпонентКонтрактБезопасное поведение при сбое
Source registryОбъявляет source ID, current version, lifecycle, scope и locatorОтклоняет update без identity или ownership
Change collectorПревращает upload, webhook или scan в idempotent jobДедуплицирует повторные events и хранит event key
Extractor и normalizerВозвращает inspectable text и extraction statusQuarantine для нечитаемого input, не индексировать догадку
ChunkerИспользует pinned configuration и source offsetsСоздаёт новый derived version, не мутирует неизвестные chunks
Index writerХранит vectors, lexical fields, filters и version lineageПишет в staged state, не продвигает partial work
Promotion gateДелает одну проверенную версию current для retrievalСохраняет prior known-good version до успешной проверки
Removal workerПрименяет delete или tombstone во всех derived storesFail closed для source до подтверждённого удаления

Разделяйте immutable source version и derived-index version. Сам документ может не меняться, а extraction, OCR, parser, chunking или embedding configuration — измениться. Сохранение обеих версий позволяет осознанно rebuild и объяснить, почему два retrieval run дали разный результат.

Ingestion должен быть idempotent и observable

Events часто дублируются, задерживаются или приходят не по порядку. Retry-safe pipeline даёт каждому запросу event ID, а каждому target state — version. Повторение того же event должно оставить тот же candidate set, а не дублировать chunks. Более новая source version не должна быть перезаписана поздним worker для старой.

ts
async function ingest(event: SourceChanged) {
  const source = await registry.get(event.sourceId);
  assert(source.version === event.version);
  assert(policy.allowsIngestion(source.scope));

  const job = await jobs.claim({ eventId: event.id, sourceId: source.id, version: source.version });
  if (job.alreadyCompleted) return job.receipt;

  const artifact = await extractNormalizeAndChunk(source, pinnedConfig);
  await stagedIndex.upsert(artifact.chunks, { sourceId: source.id, version: source.version });
  await verifyCandidateSet(source, artifact);
  await registry.promoteCurrent(source.id, source.version, artifact.receipt);
}

Псевдокод намеренно не скрывает важные решения: access metadata входит до indexing, promotion идёт после verification, а registry — не память worker — определяет current state. Если worker не может установить это состояние, он должен retry или quarantine, а не публиковать сомнительный индекс.

Update, replacement и removal — разные операции

Update обычно создаёт новую version и затем её promotes. Replacement меняет retrieval target только после полного candidate set. Removal меняет eligibility: source не должен попадать в vector retrieval, keyword retrieval, reranking input, answer citations, caches или diagnostics, которые раскрывают контент.

Используйте tombstone или removal registry, когда physical deletion асинхронен. Tombstone — немедленно применяемый retrieval filter; downstream workers затем стирают или compact derived artifacts. Сохраняйте request, owner, scope, observed completion time и exceptions. Не называйте source удалённым, если обновилась лишь одна collection.

Удаление имеет границы за пределами index. Backups, audit logs, legal retention, observability и vendor-managed replicas могут подчиняться отдельному retention policy. Явно моделируйте эти границы и привлекайте owner данных; это engineering pattern, а не юридическая консультация.

Failure modes, которые нужно спроектировать

Partial update становится current. Часть chunks записалась, но extraction упал на 48-й странице. Promotion требует expected chunk count, content hash, retrieval probes и source-version evidence, а не только успешный exit job.

Поздний event перезаписывает новую version. Retry version 7 завершается после version 8. Используйте compare-and-set source version при promotion и отклоняйте либо quarantine stale work.

Deletion пропускает secondary path. Vector index очищен, но lexical index, cache, reranker или citation lookup хранит старый passage. Ведите единый removal inventory и проверяйте все retrieval path на distinguishable fixture.

Metadata расходятся с content. Документ переехал между командами, но inherited chunk permissions остались старыми. Access scope и lifecycle — versioned ingestion inputs; при их изменении переобрабатывайте или блокируйте affected source.

Scan видит незавершённый upload. Collector индексирует файл, пока он дописывается. Нужны stable-object signal, checksum или source-side finalization event до extraction.

Метрики скрывают опасный случай. Средняя ingestion latency выглядит хорошо, пока stale sources сохраняются. Отдельно измеряйте backlog age, promotion lag, current-version coverage, removal lag и failed verification.

Соберите production acceptance set

Acceptance set строится на безопасных fixture documents с уникальными фразами, известными source IDs и разными permissions. Прогоняйте его через те же event, worker и index path, что в production.

GateКакое evidence сохранить
IdempotencyDuplicate event оставляет один canonical chunk set и receipt
OrderingСтарое completion не заменяет новую promoted version
CompletenessExpected chunks, hash, source version и locators совпадают до promotion
RetrievalQuery возвращает новую permitted version и её citation locator
AccessScope change удаляет ineligible chunks до retrieval
RemovalDeleted fixture отсутствует в vector, lexical, cache, citation и trace probes
RecoveryFailed candidate не становится promoted; prior version или no-answer route явен

Проверьте happy-path update и сбои, которые операторам действительно придётся восстанавливать: timeout после write, duplicate webhook, malformed file, re-run с новым chunking, revoke доступа и delete во время retry worker. Храните небольшой evidence record каждого run, чтобы production incident можно было восстановить без догадок по transient logs.

Контролируемый путь от prototype к production

Начните с одной source family и ограниченного corpus. Назначьте source owner, ingestion owner и on-call decision path. Зафиксируйте parser, chunker и embedding configuration. Задайте явный maximum promotion lag и безопасное поведение при его превышении: сохранить prior verified version, если policy позволяет, или вернуть прозрачный no-answer.

Затем добавьте reconciliation scan. Одна доставка event не доказывает completeness: периодическое сравнение source registry и index receipt находит missing events, orphaned chunks и failed removals. Соседние гайды о метаданных и фильтрах RAG, правах доступа в RAG и цитатах RAG разбирают контракты, которые делают индекс надёжным во время query.

До расширения corpus проверьте failure budget: что происходит, когда index отстаёт, source оспорен, приходит запрос на deletion или verification не запускается? Надёжный update path — не самый быстрый путь записи vectors. Это путь, который может показать, какая version searchable, кто может её видеть, почему она current и как безопасно перестать её выдавать.

CODE_BLOCK.TXT
require(source.id && source.version && source.hash);
require(event.idempotencyKey && policy.allows(source.scope));
require(candidate.chunkCount === expected.chunkCount);
require(candidate.scope === source.scope);
require(testSet.duplicate && testSet.outOfOrder && testSet.remove);

if (!verification.complete) route = "retry-or-quarantine";
if (removal.pending) route = "exclude-from-retrieval";