Коли пам'ять агента стиснуто в короткі коди, чи погоджуються два ШІ на одній хибній відповіді?
разом із Mohan Bheemadolu · розробник ШІ-агентів, Редмонд · співавтор FlyHash for LLM agent memory
За півхвилини
Mohan Bheemadolu і Dr. Chrisogonas O. Odhiambo написали FlyHash: спосіб зберігати спогади ШІ-агента як дуже короткі двійкові коди за зразком того, як ніс плодової мушки розрізняє запахи. При однаковому розмірі коду він знаходить потрібний спогад приблизно в 2,5 раза частіше за звичний SimHash. Звідси питання, на яке жоден із нас не міг відповісти сам. Агентів часто перевіряє другий ШІ, але обидва ШІ читають ту саму знайдену пам'ять. Якщо менша пам'ять частіше пропускає факт, чи починають два перевіряльники погоджуватися на тій самій хибній відповіді? Перший прогін зі звичайною пам'яттю свідчить, що можуть: коли пам'ять пропускала докази, 45% відповідей, на яких погодилися обидва ШІ, були хибними, проти 3%, коли докази в ній були. Це був один ретривер і один сід, тож це асоціація, а не причина. План Mohan: виміряти FlyHash на чотирьох розмірах коду на тому самому бенчмарку й надіслати знайдені пам'яті; перевірка згоди запуститься на них.
Стаття
Агент, що пам'ятає минулі розмови, має десь їх зберігати і швидко знаходити потрібний шматок. FlyHash запозичує з нюху плодової мушки: він перетворює ембедінг кожного спогаду на короткий розріджений код, у якому ввімкнено лише кілька «активних бітів». Короткі коди — це мала пам'ять.
Результати в статті на диво прості. При однаковому розмірі коду FlyHash знаходить потрібний спогад приблизно в 2,5 раза частіше за SimHash (0,27 проти 0,11). Коли пам'ять не обмежена, стандартний індекс HNSW усе одно випереджає обох, і автори так і кажуть. Статті, що прямо називають, де їхній метод програє, трапляються рідше, ніж мали б, і саме це спонукало нас їм написати.
Код відкритий: github.com/mohanji/flyhash-agent-memory.
Як минула розмова
Усе почалося в коментарях під статтею на Hugging Face. Ми спитали, як коди справляються з питаннями, сформульованими вільно, а не за шаблоном. Mohan відповів, що досі тести йшли із шаблонними формулюваннями, і спитав, який датасет ми порадимо. Ми запропонували два, зібрані з довгих реальних багатосесійних діалогів: LoCoMo і LongMemEval. Він вирішив почати з LoCoMo, а далі взятися за LongMemEval.
Потім ми поставили питання, що зв'язує його роботу з нашою: чи програватимуть найкоротші коди більше на питаннях про час («коли вона переїхала?»), ніж на поодиноких фактах?
Чому пам'ять важлива для двох ШІ, що перевіряють одне одного
Коли дві моделі від різних компаній погоджуються на відповіді, це часто вважають добрим знаком. Але в агенті обидві моделі зазвичай читають ту саму знайдену пам'ять. Якщо ретрівал пропустив факт, вони вже не незалежні: вони можуть упевнено погодитися на одній і тій самій хибній відповіді.
Щоб побачити, як часто таке трапляється, ми зібрали невелику відкриту перевірку на LoCoMo, memory-agreement-check, і запустили її один раз зі звичайною ключовою пам'яттю (BM25, топ-10 реплік діалогу). GPT і Claude відповідали окремо, а Kimi оцінював їх наосліп.
Помилки двох моделей сильно корелювали (φ = 0,81). Це один ретривер і один сід, тож це асоціація, а не причина. Але це дає FlyHash точне питання, на яке відповісти.
Експеримент, який ми проводимо разом
Mohan запропонував надати сторону ретривалу; далі ми беремо на себе.
- Mohan спершу вимірює ретрівал: recall@k для кожної категорії LoCoMo (single-hop, multi-hop, temporal) на кількох розмірах коду FlyHash і SimHash, 16, 32, 64 і 128 активних бітів, з топ-10 спогадів на питання, як у першому прогоні.
- Ми запропонували додати ще й топ-5: менше спогадів означає більше пропусків, а це має показати, як швидко зростає частка впевнено хибних узгоджених відповідей.
- Він надсилає знайдені контексти як JSONL, один рядок на питання.
- Ми запускаємо перевірку згоди на кожному файлі й надсилаємо йому результати.
Питання, яке ми прочитаємо в кінці: чи зростає з вкороченням кодів частка відповідей, на яких обидва ШІ погодилися і помилилися, і чи зростає вона найшвидше для питань про час? Якщо так, у меншої пам'яті є прихована ціна, яку перевірка другим ШІ не піймає. Якщо ні, FlyHash виглядає навіть краще, ніж каже стаття.
Код
Перевірка приймає вивід будь-якого ретривера. Один рядок на питання:
{"qid": "conv-26/0", "memories": [{"text": "[D1:3 | 1:56 pm on 8 May, 2023] Caroline: I went to a LGBTQ support group yesterday...", "dia_id": "D1:3", "score": 0.82}]}У репозиторії вже є приклад, що будує ці контексти класами FlyHash і SimHash з коду Mohan:
git clone https://github.com/mohanji/flyhash-agent-memory
pip install numpy sentence-transformers
python examples/flyhash_contexts.py --flyhash-src flyhash-agent-memory/src \
--method flyhash --active-bits 32 --out flyhash-k32.jsonl
python -m memcheck run --backend cli --contexts flyhash-k32.jsonl --memory-name flyhash-k32Якщо прогнати ті самі питання на кількох розмірах коду або проти --method dense як еталона, вийде порівняння.
Що перші цифри можуть і не можуть сказати
- Вони з одного ретривера (BM25), однієї пари моделей, одного судді й одного сіду, на 200 питаннях. Інші ретривери й моделі можуть зрушити кожну цифру.
- Питання, докази до яких BM25 пропускає, відрізняються від решти (multi-hop і open-domain пропускаються набагато частіше), тому порівняння робиться ще й всередині кожної категорії.
- Причинний тест відповідав би на ті самі питання один раз із репліками-доказами, а другий без них. FlyHash на кількох розмірах коду — природний крок до цього: ті самі питання, ті самі моделі, змінюється лише пам'ять.
Хронологія
- Mohan Bheemadolu і Chrisogonas O. Odhiambo публікують FlyHash на arXiv (2611.05791).
- Стаття з'являється на Hugging Face Papers. У коментарях ми питаємо про перефразовані питання; Mohan питає, який датасет узяти; ми пропонуємо LoCoMo і LongMemEval, і він обирає спершу LoCoMo.
- Ми питаємо, чи програють короткі коди більше на питаннях про час. Відкрита перевірка вперше запускається на 200 питаннях LoCoMo, з прикладом для FlyHash, і ми надсилаємо Mohan цифри.
- Mohan викладає план: recall ретривалу за категоріями на 16, 32, 64 і 128 бітах при k = 10, контексти як JSONL. Ми погоджуємося й додаємо k = 5.