Comments 23
Заявление "от 38% к 87%" на графе впечатляет, но держится оно на Closes #N. А с точностью самих рёбер как? Как часто PR закрывает не тот issue или Closes проставлен вручную мимо? Считали точность связей отдельно, прежде чем приписать графу +49 пунктов?
Точность рёбер отдельно не считали - тут пока пробел; но +49 п.п. меряется на held-out gold-парах, а ложное ребро уводит обход и recall занижает, а не раздувает, то есть выход на 87% скорее пол для чистого набора рёбер. Точность рёбер добавим отдельной цифрой.
Да память ценна не как эхо прошлого, а как горизонт настоящего!
Одна вода и ни одного бенчмарка.
Бенчмарк в статье есть, он под спойлером «Как мы намерили 87%».
Чего в первой статье нет — замеров latency и сравнения с pgvector: это будет третья статья, про HNSW руками.
Как можно сделать выбор на основании того что вы называете бенчмарком? С кем вы соревнуетесь? а еще у вас куча технических решений, а где обляционные исследования, было бы интересно понять насколько они работают?
Как делать выбор — никак, это про наш корпус. Прогнали, получили своё число. На чужом репозитории ydb-platform/ydb, 293 пары: 32.1% против 94.5% — то есть мы проверяем не значение, а разрыв.
Мы не соревнуемся — это A/B одного компонента (тот же корпус, энкодер, запросы, top-k; меняется только «ходим по рёбрам Closes #N или нет»).
Да, про абляции: они есть — и половина наших решений их не пережила: важность в ранге проиграла (0.41 против 0.81 у чистого косинуса) всеми четырьмя способами подмешивания, RRF оказался худшим (0.06), так что важность мы из ранга выкинули, а PPR оставили опцией.
Прямо сейчас провели исследование на открытом репозитории YDB (Yandex Database) — ydb-platform/ydb — результаты публикуем без ретуши как обновление к этой заметке, также потом сделаем отдельную статью, потому что тема очень интересная.
чем больше кеша тем дороже но выше качество и наоборот, смысл освобождать кеш? Мы из крайности в крайность как то
Дорого не хранение — диск копеечный, мы ничего не удаляем.
Дорого извлечение: в контекст уходит фиксированный top-k, и каждый лишний почти-дубликат занимает слот, который стоил бы нужному факту. Отсюда третий закон статьи: частый плотный сигнал топит редкий, но ценный (популярный узел топит точный факт, хабы зарывают specific, плотные similar_to глушат редкие caused_by). Поэтому «освобождать» — это не про забыть, а про то, что попадает в горячий индекс: decay/вытеснение мы применяем к частому классу и никогда — к редко-ценному. Он живёт отдельным механизмом: изолированный причинный обход + повторные грабли (revert 39 раз, xsrf 60) подмешиваются первым блоком в каждый recall.
То есть, не «из крайности в крайность», а две разные политики для двух классов памяти. Крайность как раз «сложить всё в один индекс и надеяться, что редкое само всплывёт» — именно это даёт 38% вместо 87%.
👍👍👍
Полностью согласен с тезисом, что память начинает приносить пользу ровно тогда, когда возражает автору. Мы пришли к тому же, но с другого конца и на куда более примитивной технике. У нас агенты работают с реальными клиентскими данными, и память это не векторный граф, а плоские markdown-файлы плюс жёсткое правило в системном промпте: прежде чем утверждать что-либо про состояние системы, перечитай запись, не отвечай по памяти сессии. Ретривер тут вообще никакой, вся сила в том, что обращение к памяти детерминированное, а не на добрую волю агента. Ваш вывод про хук вместо надежды на сознательность модели по нашему опыту важнее, чем качество самого поиска. Свежий пример буквально сегодня. Агент готовил клиенту отчёт по рекламной кампании и уверенно написал ложную причину одного события. Сработали запись в памяти и правило перепроверки, агент полез в API за фактом, поймал своё же враньё и переписал до отправки. Память сработала именно как возражение, а не как справочник. Реализация примитивная, а эффект тот же, что вы описываете на графах.
Очень полезная статья.
Заявление "от 38% к 87%" на графе впечатляет, но держится оно на Closes #N. А с точностью самих рёбер как? Как часто PR закрывает не тот issue или Closes проставлен вручную мимо? Считали точность связей отдельно, прежде чем приписать графу +49 пунктов?
Про важность узла: вы её выкинули, потому что MRR просел от 0.81 до 0.41. Но это был фиксированный линейный бленд? Обучаемые веса, RRF с подбором пробовали? Подозреваю, вы могли похоронить полезный сигнал из-за плохой калибровки веса, а не потому что важность вредна.
Ключевой момент, и фичу мы выкинули не потому, что важность бесполезна. Провалился не один линейный бленд — проиграли чистому косинусу все четыре способа смешать сигнал (сумма, гейт, RRF, PPR) на реальных парах "запрос - ответ".
Причина глубже калибровки: знак пользы важности зависит от интента запроса — на хабовых запросах важность помогает (на синтетическом графе вытаскивает MRR с 0.033 до 1.0), на запросах про конкретный редкий факт — топит его (0.81 -> 0.41). Любой статический вес поэтому неверен по форме.
Правильное лекарство — вес, зависящий от запроса/обратной связи; это осознанный план действий, а не тупик. PPR оставлен опцией, из дефолтного ранга важность убрана.
Вывод "абсолютный порог по косинусу не переносится нигде" вы делаете на 246 узлах и 300 запросах одного корпуса. Это уже закономерность или всё же свойство связки MiniLM + ваши dev-логи? Что вы меняли (модель, домен, язык), прежде чем назвать это законом?
Да, один корпус, и универсальной теоремы мы не заявляем. Переносится не число, а процедура: "не гадать порог абсолютного косинуса, ранжировать top-k, мерить на своих данных". Именно потому, что число поехало — между синтетикой и реальностью, и поедет между корпусами. Механизм не экзотичен: мультиязычные энкодеры (MiniLM-семейство) держат косинус в узком высоком диапазоне, из-за чего облака "соседи" и "случайные" перекрываются.
Мы не прогоняли десяток моделей — это субъективная граница замера. Но безопасный вывод "ранжируй, а не ставь пороги" от модели не зависит.
Не дали ИИ-агенту соврать — его же памятью