Перейти к основному содержимому

Retrieval and memory

После главы вы сможете выбрать между domain tool, retrieval и memory, а также измерить retrieval отдельно от качества final answer.

Не всё прошлое — память​

ОбъектПримерSource of truthТипичный срок
Transcript«Где мой заказ?»Conversation storePolicy-dependent
Task statepending approvalEvent projectionДо terminal/retention
Observationget_order rev 5Domain system + eventДо invalidation
User memoryязык ответаExplicit preference storeДо удаления/изменения
Episodic memoryпрошлый успешный сценарийCurated outcomeОграниченный
Knowledgecargo policyVersioned corpus/APIПо версии документа

Сохранить transcript навсегда и назвать это memory — не архитектура: нет namespace, consent, freshness и deletion semantics.

Tool или retrieval?​

API-shaped факты лучше читать domain tool: order status, balance, slots. Document-shaped знания подходят retrieval: policy, manuals, product comparison, FAQ.

точный изменяемый record → domain API/tool
неструктурированный корпус → retrieval
устойчивая user preference → scoped memory
текущий progress → task state

Поэтому RAG не обязателен каждому агенту. Для telehealth booking slots важнее API; для pharmacy/policy Q&A — retrieval.

RAG pipeline​

Failure может возникнуть на каждом слое. Нельзя лечить низкий recall изменением final prompt.

Chunking​

Fixed-size​

Просто и воспроизводимо, но разрывает таблицы, исключения и определения.

Structural​

По headings/sections/records. Лучше сохраняет смысл, требует parser для каждого формата.

Semantic/task-aware​

Строится вокруг возможных вопросов или entities. Может улучшить retrieval, но дороже, сложнее обновляется и рискует закодировать текущие use cases.

Хороший chunk сохраняет provenance: source URI, version, section, effective date, access label.

Метрики retrieval​

  • Recall@k: доля всех релевантных документов, найденных в top-k: |top-k ∩ relevant| / |relevant|.
  • Hit@k: нашёлся ли хотя бы один релевантный документ. Если релевантных два, а найден один, Hit@k равен 1, Recall@k — 0.5.
  • MRR: насколько рано появился первый релевантный результат.
  • nDCG: учитывает порядок и градуированную релевантность.
  • Filter/authorization recall: не отрезали ли нужное; не показали ли запрещённое.
  • Freshness: соответствует ли найденная версия effective policy.

Answer groundedness не заменяет retrieval eval: модель не может процитировать документ, который pipeline не нашёл.

Memory write policy​

Наивная схема записывает каждую фразу пользователя. Она быстро накапливает ошибки и sensitive data.

Перед записью спросите:

  1. Пользователь явно выразил устойчивую preference/fact?
  2. Есть consent и lawful purpose?
  3. Каков namespace: thread, user, tenant?
  4. Как подтвердить/изменить/удалить record?
  5. Когда истекает TTL?
  6. Как provenance попадёт обратно в context?

Model-generated inference вроде «пользователь, вероятно, богат» не должна автоматически становиться долговечной памятью.

Namespace isolation​

Helios memory store возвращает tenant-scoped records плюс records точного thread. Record tenant-alpha не виден tenant-sol; preference thread-1 не переносится в thread-2.

Production identity обычно сложнее: organization, workspace, end user, legal region, purpose and sensitivity labels. Filter должен выполняться до semantic ranking и повторно на выдаче.

Freshness и provenance​

Для каждого retrieved item полезны:

  • stable source ID;
  • source version/effective time;
  • retrieved_at;
  • access scope;
  • relevance score и retriever version;
  • transformation/chunk lineage.

Если cargo rule обновилась, старое memory нельзя «исправить» красивым summary. Нужна invalidation/re-index и domain policy check на актуальной версии.

Deletion и retention​

Удаление source требует ответа на вопросы:

  • удалить chunk из index;
  • удалить embeddings/cache;
  • перестроить summaries, где он использован;
  • сохранить минимально необходимый audit без исходного content;
  • прекратить future retrieval;
  • доказать completion deletion job.

Для PHI/PII de-identification снижает риск, но не превращает данные в свободный учебный corpus. Назначьте purpose, access, retention и deletion до выгрузки.

Стратегии​

РешениеВыигрышЦенаКогда плохой выбор
Full corpus in contextНет retrieval missTokens/latency/leakageБольшой corpus
Lexical searchПрозрачно, дешёвоСлабые paraphrasesСемантически разнообразные вопросы
Dense retrievalSemantic recallModel/index lifecycleExact IDs/codes
Hybrid + rerankerОбычно сильнееLatency и eval complexityМалый low-traffic corpus
Domain APIСвежий structured stateНужен integrationДокументы/объяснения

Helios и реальный аналог​

Пользователь спрашивает cargo restrictions. Order route читается tool, а нормативные исключения ищутся в versioned corpus с jurisdiction metadata. Перед booking policy service проверяет правило ещё раз; retrieved paragraph помогает объяснить, но не авторизует shipment.

Лаборатория​

npm run test:course:pattern -- "memory|stale"

Добавьте memory другой tenant и убедитесь, что retrieval его не возвращает. Затем перейдите к эксперименту ниже: он отдельно показывает ошибки поиска и ограничения найденных evidence.

Лаборатория: от корпуса до выдержки с источником​

Нужны Python 3.12 и uv 0.12.7; подготовка окружения. Из корня репозитория:

uv run --directory examples/helios_ml --frozen python scripts/compare_retrieval.py

Корпус synthetic-cargo-v1 содержит правила доставки, возврата, рекламный текст, старую версию правил и документ другого tenant. Source.sections задаёт уже разобранные заголовки и тексты. build_chunks сохраняет каждый раздел целиком, с source ID, версией и namespace; это structural chunking после parsing. PDF/HTML parser в лабораторию не входит.

Путь данных:

trusted source metadata → structural chunks → tenant/current filter
→ candidate retrieval → optional heading rerank → top-k → verbatim extracts

current назначается ingestion-процессом, а tenant приходит из execution context. Модель не может назначить эти значения. В учебном корпусе source IDs глобально уникальны, для одного source допускается только одна current-версия. В production нужны собственные контракты identity и effective dates.

Сравнить по одному изменению​

МетодПредставление / ранжированиеЧто меняется относительно предыдущего
wordСуществующий TF-IDF по словам и биграммамИсходный baseline
charTF-IDF по символьным n-граммам длины 3–5Только лексическое представление
char_headingТе же char candidates, сначала больше точных совпадений слов заголовка, затем scoreТолько порядок уже найденных candidates

Все методы используют один корпус, фильтры и k. По умолчанию candidate_k=4, k=1. Reranker не читает gold labels и не может вернуть chunk вне своих candidates. Score остаётся исходным retrieval score; после перестановки его значения могут идти не по убыванию.

Это два лексических baseline и rule-based reranker. Здесь нет dense embeddings, hybrid fusion, cross-encoder или генеративной LLM. Цель первого опыта — увидеть и локализовать ошибки на прозрачной реализации, прежде чем подключать более сложные компоненты.

Ожидаемые наблюдения​

CaseНаблюдение при k=1Что это объясняет
word_formword не находит «посылки»; char находит раздел «Посылка»Лексическая форма может быть причиной miss
exceptionНаходится текущий раздел про батареи вместе с исключениемChunk должен сохранять ограничение, а не только общее правило
headingword и char ставят рекламу выше правил; char_heading возвращает правилаCandidate retrieval и порядок выдачи — разные этапы
missing_factВсе методы находят правила, Recall@1=1, но точной суммы возврата там нетRetrieval relevance не доказывает answerability
no_overlapПустая выдача и abstain; Recall/RR равны nullДля пустого gold relevant set эти метрики здесь не определены

В отчёте reciprocal_rank относится к одному запросу; среднее по запросам с непустым relevant set даст MRR. gold_answerable_from_corpus — разметка evaluator; она не передаётся поиску и не вычисляется из score.

Что означает результат​

extract_response возвращает только буквальные выдержки и citation IDs выбранных chunks. При непустой выдаче статус — evidence_only, а не «вопрос решён». При отсутствии положительного лексического score — abstain. Это ограниченная эвристика отсутствия совпадений: даже маленький положительный score ещё не означает полезный ответ.

В missing_fact нужно перейти к order/refund API. В настоящем RAG после context selection добавляется model call; отдельные graders проверяют, подтверждают ли выдержки каждое утверждение ответа и достаточно ли их для вопроса. Ссылка на существующий chunk не доказывает корректность сгенерированного текста.

Три контролируемых эксперимента​

  1. Запустите --k 2 --candidate-k 4. Запишите, какой relevant chunk теперь вошёл в выдачу и сколько лишнего контекста добавилось. Рост recall не обязательно улучшит final answer.
  2. Запустите --k 1 --candidate-k 1. В heading reranker уже не может поднять правила: их нет среди candidates. Причина — раннее отсечение, а не плохой final prompt.
  3. В учебной копии источника перенесите исключение о повреждённых батареях в отдельный раздел и задайте оба chunk IDs как релевантные вопросу «когда батареи принимаются и когда запрещены». При k=1 Recall@1 не может превысить 0.5. Не меняйте разметку, чтобы скрыть потерю условия.

Артефакт: таблица «один изменённый фактор → rankings → метрики → ошибка → следующее действие». До запуска запишите прогноз; после запуска объясните расхождение. Критерий готовности — локализовать проблему на ingestion, retrieval, reranking или answerability, а не просто получить высокий средний score.

Следующий уровень: dense, hybrid и генерация​

На отдельном, более разнообразном корпусе можно последовательно добавить learned embeddings, затем объединение lexical/dense rankings, затем trained reranker и генеративный ответ. Сохраняйте те же cases и filters, версионируйте embedding model/index и отдельно измеряйте затраты каждого этапа. После настройки на development set нужна проверка на новых frozen cases.

Это продолжение самостоятельного эксперимента, не реализованная возможность текущего CLI. Синтетические пять запросов специально демонстрируют разные ошибки; преимущество метода на них не переносится на реальный корпус. Исходная работа RAG исследует сочетание retrieval и генерации; данная лаборатория изолирует только подготовку evidence.

Self-check​

  • Это API-shaped или document-shaped вопрос?
  • Как измеряется retrieval до model call?
  • Где применяются tenant/access filters?
  • Как отмечается версия и freshness?
  • Какие записи memory создаются только с consent?
  • Как выполнить deletion во всех производных stores?
  • Почему Hit@k и Recall@k расходятся при нескольких релевантных chunks?
  • Может ли reranker восстановить отсутствующего candidate?
  • Как отличить найденный документ от достаточного ответа?

Источники для лаборатории​

Проверено 2026-09-07: Introduction to Information Retrieval: ranked evaluation — определения и интерпретация метрик; scikit-learn: feature extraction — word/character TF-IDF; Lewis et al., RAG, 2020 — исследование retrieval-augmented generation. Правило heading rerank и конкретный корпус — учебная эвристика.