Исследования ИИ

Почему мы отказались от vector-only retrieval для памяти агентов — и что используем вместо

Vector-only retrieval красиво выглядит на демо, но ломается на реальных данных агентов. Разбираем три режима отказа и архитектуру гибридного стека, который их решает.

6 апреля 2026 г.
6 мин чтения
RAGвекторный поискэмбеддингипамять агентовLLMBM25pgvectorhybrid retrieval

Иллюзия простоты

Стандартный рецепт памяти AI-агента выглядит элегантно: берём pgvector, генерируем эмбеддинги через OpenAI, ищем по cosine similarity. Три строчки кода — и агент «помнит». На демо всё работает. На продакшене — нет.

Мы прошли этот путь целиком. Полгода vector-only в проде, тысячи запросов в день, нарастающее разочарование. Три конкретных failure-режима заставили нас пересмотреть архитектуру с нуля.

Failure #1: точные идентификаторы

Пользователь спрашивает: «Какой API-ключ я использовал для проекта X?» Агент уверенно возвращает... не тот ключ.

Проблема фундаментальна. Cosine similarity работает с семантической близостью. Строка sk-proj-abc123 семантически неотличима от sk-proj-xyz789 — обе «API-ключи». Embedding-модель сжимает токены в плотный вектор, где точное значение идентификатора растворяется.

То же самое с UUID, номерами заказов, хэшами коммитов, IP-адресами. Любая строка, где важен каждый символ, а не общий смысл — blind spot для vector search.

Failure #2: редкие proper nouns

Второй класс провалов — имена собственные, которых нет в обучающей выборке embedding-модели. Названия внутренних проектов, нестандартные аббревиатуры, имена контрагентов из неанглоязычных рынков.

Embedding-модель не знает, что «Проект Байкал» — это ваш внутренний ML-пайплайн. Она видит «озеро в Сибири» и услужливо подтягивает документы про географию. Proper nouns вне распределения обучающих данных превращаются в шум.

Замеры на корпусе из 12 000 записей агентской памяти: точность retrieval по proper nouns падала до 34% (против 78% на обычных семантических запросах). Треть времени агент доставал не те документы.

Failure #3: отсутствие хронологии

Третий — и самый коварный — провал. Пользователь спрашивает: «Что изменилось в конфигурации за последнюю неделю?» Vector search не знает, что такое «неделя». Он находит все семантически близкие документы про конфигурации — из прошлого месяца, прошлого года, из другого проекта.

Cosine similarity — это расстояние в семантическом пространстве. Времени в этом пространстве нет. Можно добавить дату в текст чанка, но embedding-модель обрабатывает её как ещё один набор токенов, а не как метаданные для фильтрации.

Для памяти агента хронология критична. Агент должен знать: «Сначала было A, потом B изменило ситуацию, сейчас актуально C». Vector-only retrieval возвращает A, B и C вперемешку и предлагает LLM разобраться. LLM не разбирается — галлюцинирует.

Архитектура гибридного стека

Решение — не отказаться от векторов, а дополнить их. Три компонента, каждый закрывает свой failure-режим.

BM25 для точных совпадений

BM25 — классический алгоритм текстового поиска. Работает с точными токенами, не с семантикой. Когда пользователь ищет конкретный идентификатор, BM25 находит именно эту строку.

Реализация: PostgreSQL full-text search (tsvector/tsquery) рядом с pgvector в той же базе. Нулевой overhead по инфраструктуре. Ключевой момент: конфигурация 'simple' вместо языковой — не стемит токены, поэтому идентификаторы, IP-адреса и proper nouns сохраняются как есть.

pgvector для семантики

Семантический поиск остаётся. Он отлично работает для запросов вроде «как мы решали проблему с таймаутами» — где важен смысл, а не точное слово. Запросы к BM25 и vector выполняются параллельно, результаты объединяются через Reciprocal Rank Fusion.

Temporal metadata для хронологии

Каждая запись памяти получает три поля: created_at, updated_at, event_timestamp. Третье поле — время события, о котором говорит запись (не время вставки в базу). Для запросов с временным контекстом парсим временные маркеры из запроса и превращаем их в SQL-фильтры до ранжирования.

Reciprocal Rank Fusion: как объединять результаты

Два ранжированных списка (BM25 и vector) нужно объединить в один. Reciprocal Rank Fusion (RRF) — стандартный подход: для каждого документа суммируем 1/(k + rank) по всем спискам, где k=60. RRF не требует нормализации скоров между BM25 и cosine similarity — они в разных шкалах, работает только с позициями в рейтинге.

Когда переключаться на гибрид

Не каждому проекту нужен гибридный retrieval с первого дня. Три сигнала, что пора:

  • Идентификаторы в памяти. Если агент хранит API-ключи, UUID, номера тикетов, IP-адреса — vector-only будет ошибаться. Это не вопрос тюнинга, это фундаментальное ограничение.
  • Доменная терминология. Внутренние кодовые имена проектов, специфичные аббревиатуры, имена на нелатинских алфавитах — всё, что embedding-модель не видела при обучении.
  • Временные запросы. «Что было на прошлой неделе?», «Покажи изменения после релиза» — если агент должен отвечать на такие вопросы, без temporal metadata не обойтись.

Результаты

На корпусе из 12 000 записей после перехода на гибридный стек: общий Recall@10 вырос с 72% до 91%. По идентификаторам — с 23% до 94% (четырёхкратный рост). По proper nouns — с 34% до 87%. По временным запросам — с 41% до 89%. BM25 делает ровно то, для чего создан: находит точные совпадения строк.

Что это значит для архитектуры агентов

Vector DB — мощный инструмент, но не серебряная пуля для памяти агентов. Память — это не «найди похожее». Это «найди точно то, о чём спрашивают, в правильном хронологическом контексте».

Гибридный стек добавляет сложности — два индекса вместо одного, fusion-логика, парсинг временных выражений. Но эта сложность оправдана, когда агент работает с реальными данными: ключами, конфигами, историей событий.

Если ваш агент оперирует только абстрактными знаниями из документации — vector-only может быть достаточно. Если он работает с конкретными фактами, идентификаторами и хронологией — гибрид не опция, а необходимость.

Автор: Алик Завалишев

Эксперт по ИИ и автоматизации процессов

Больше статей