Памяць агента: акно кантэксту, RAG і пастаянны стан
Памяць агента — гэта тры розныя рэчы. Чым адрозніваюцца акно кантэксту, пошук і пастаянны стан, колькі каштуе кожнае і як спачатку выбраць патрэбнае.
Крыніцы: Agent Memory Explained
Мало які словы спрычынаюць столькі плутання ў розвіцці агента, як слова „памяць“. Калі хтось кажа, што ў яго агента ёсць памяць, гэта можа значыць, што розмова дужа дзейнаўская, або што падключана база даных у вектарнай форме, або што факты зберагаюцца у файле, які застаецца пасля перзапуску. Цэлкам трохі разныя сістэмы з рознымі вітратамі, рознымі спосабамі выключэння і рознымі прычынамі існавання.
Одна фраза розвяляе большасць плутання. Мадэль не мае памяці, у яй толькі вхідны даны, а то, што люды называюць памяцью, — гэта проста правіла для выбору таго, што будзе включанае у этыя вхідны даны.
Мадэль ў стане „без стану“. Кожны вызов API пачынаецца з нуля, без жадных спомненняў пра вашу пярэднюе паведамленне, пярэдняю сесію чы імя, якое вы ёй далі. Тое, што яна знае пад час вызову, — гэта толькі тое, што ўключанае у запіт, і нічога больш.
Таму важным пытаннем не ёсць тое, чыяе у агента памяц. Гэта тое, што здобывае месца ў гэтым запытанні, і звядзе гэта. Існуе тры адпаведныя адказы, і задача — развідрóżніць іх.
Мадэль без стану, прыкладнэць з станам
Новачкі прыпускаюць, што мадэль ведае размову. Гэта не так. Размову ведае прыкладнэць і павтарае яе. Калі вы апрашываеце чат-паведамленне чатвертае, ваш код ўсё разы перадае паведамленні 1, 2, 3 і 4. Адчуванне працягласці выходзіць з перадачы історыі, а мадэль проста получае дэльнейшы вхід, чым раней.
З урахоўваннем гэтага тры слоі перастаюць быць абстрактнымі:
- Вікна кантэксту — гэта тое, што зараз знаходзіцца ў запытанні.
- Рэтрыбуцыя (RAG) — гэта спосаб, якім вы знаходзіце матэрыял для дадання ў запытанні.
Кантэйнер, справач і хранальнік — тры разныя рэчы. Калі іх змешаць, то вы будзеце вікорыстоўваць базу дадзеных тыпу vector database для рашэння проблемы, яку мог бы рашыць файл preferences.json.
Слой 1: вікна, або стол модэлю
Уявіце вікна як усё, што модэль можа зараз бачыць. Сістэмны запрос, історыя, апісанні інструментаў, рэзультаты ўпрымку інструментаў, запрашаныя дакументы і тэкст адпаведзі, які пішчыцца, — усе гэта выкарыстоўвае аднаковы бюджэт токенав.
Уявіце стол. Усё, пра што модэль павінна рассудзіць, должна быць фізычна на ям, а шухлядны сундук у іншай камнаце не пісаецца.
Якое ў яго сілу: мгновенна рэакцыя. Усё, што знаходзіцца ў вікні, абсалютна відна без додатковых пошукоў, і мадэль можа аналізаваць усё гэта заодно. Для задачы з обмежаным, вядомым калекцыяй матэрыялу заполненне вікна — гэта простэйшы і часта правільны спосаб.
Кошты:
- Грошы і затрымкі залежаць ад таго, што вы перасылаеце. Перасылка 51 раунду дзяўнае чат-розмовы перасылае 50 раундоў історыі. Дзяўны кантэкст не ёсць безкоштовным проста таму, што ён пасходзіць.
- Увага распадзецца неравнамерна. Мадэлі зазвычай наўмоцней вікорыстоўваюць пачатак і канец дзяўнага вхіднага даных, а серэдзіну — менш, гэта шырока вядомы эфект „загублення ў серэдзіне“. Факт, які знаходзіцца на 60% дужа дзяўнага запіту, ёсць прысутным, але можа ніколі не быць эфектываў вікорыстаны. Тое, што пасходзіць, не значыць, што яго чытаюць.
Усю гэтую схему можна выразіць за калькі ліній:
messages = []
def turn(user_text):
messages.append(
{"role": "user",
"content": user_text}
)
# every call resends
# the ENTIRE history
reply = client.messages.create(
model="claude-opus-5",
max_tokens=1024,
messages=messages,
)
messages.append(
{"role": "assistant",
"content": reply.content[0].text}
)
return reply
# messages grows forever.
# so does your bill.
Эты спіс ў даным случае являе сабою „памяць“. Ён існуе толькі ў вашым працэсе, таму як толькі працэс завершыцца, спіс таксама знікне.
Сама вікна ўсё, што трэба, калі задачэ ўскорыта, неабходны матэрыял незначны і вядомы загадзя, і нічога не павінна перазіць сеанс. Для стварэння падсумку, перагледу адной файловай дастаткова толькі гэта. Не трэба дадаўаць дапаможных прыемоў.
Слой 2: адзыскванне, бібліятэка-рэферэнс
Раней чы пазней матэрыял стае занадта велікі або болей не варты выкарыстання. Можа, гэта 10 000 запітоў на падтрымку, внутршня вікі чы база коду. Нельга помешчаць усё гэта ў кожны запіт, і не трэба.
Генераванне з адзыскваннем дадатковых даных дзеліць працу: загадзя ствараецца індэкс, а потым шукаюць неабходную інфармацыю, калі з’яўляецца запіт.
Спачатку вы разрываеце дакументы на часткі, ператвараеце кожную частку ў эмбедынг (чыслаўы вектар, які фіксуе значэнне) і зберагаеце яго. Калі прыходзіць запіт, вы таксама ператвараеце яго ў эмбедынг, знаходзіце тыя часткі, чыя вектары знаходзяцца найбліжэй, і вставляеце іх у вікно кантэксту па боку запіта.
# 1. AHEAD OF TIME (once, offline)
for chunk in split(documents):
store.add(
text=chunk,
vector=embed(chunk),
)
# 2. AT QUESTION TIME (every request)
def answer(question):
hits = store.search(
embed(question), top_k=5
)
context = "\n\n".join(h.text for h in hits)
return client.messages.create(
model="claude-opus-5",
max_tokens=1024,
# retrieved chunks land in the same request
messages=[{
"role": "user",
"content": f"{context}\n\nQ: {question}",
}],
)
Зверніце ўвагу на тое, што насправды адбылася. RAG не даў модэлю памяці. Ён даў вам стратэгію выбору фрагментаў. Адзысканыя фрагменты падаюць у той жа запіт, што і ўсё інша, таму RAG являе сабою спосаб прыема дадзеных у Першы шар, і няма для яго жадных альтэрнатываў.
Адрозкі: масштабаванне і свежасць. Мільйоны дакументаў можу змяніцца незалежна ад вашага коду, тады калі модэль бачыць толькі тые фрагменты, якія маюць значэнне для данага запіту.
Косты:
- Рэзультат вяршыцца з самага пачатку. Размер фрагментаў, модэль укладання дадзеных і дыяграма індэксу зафіксаваныя ў момент стварэння індэксу. Факт, які розпадаецца на два фрагменты, або сформульваны не так, як пытаюцца корыстнікі, проста не знаходзіцца, і тады модэль адпавядае з упэўненасцю на адной з тых інформацыях, якія ён отрымаў. Для спостэрагача паслабленыя рэзультаты адзыскання дадзеных і галюцынаціі выглядаюць аднакова.
Метод адзыскання інфармацыі падходзіць, калі база знанняяў веліка, спольна для всіх корыстувачаў і рэдка зміняецца, напрыклад, дакументацыя, правілы, каталогі продуктав і код. Адзнака заключаецца ў тым, што адна база дадзейнаў служыць усім корыстувачам. Калі тое, што вы хочаце запамятаць, належыць аднаму корыстувачу і зміняецца пад час разговору, метод адзыскання інфармацыі ёсць няпадходжым, і тады вам патрэбна трэцяя складовая.
Трэцяя складовая: стойкі стан, зошыт
Стан, які застаецца, — гэта тое, што застаецца пасля завершэння процэсу. Цэла не тое, што агент ведае пра свет, а тое, што ён вывучыў і чыя інфармацыя павінна застацца пасля завершэння данай сесіі: прагантыкі корыстніка, контрольныя пункты задання, вжытыя раней рашэнні, спробаваныя, але адмовленыя варыянты, стыслыя падсумкі пакульшых запускаў. Цэлі маленькія, конкрэтныя, цінныя факты, якія сам агент запісаў.
Шаблон складаецца з цыклу чытання, змены і запісу, які працюе працоўна ў межах сесіі:
# session start: load
with open("state.json") as f:
state = json.load(f)
system = (
"Known about this user:\n"
f"{json.dumps(state)}"
)
messages = []
def turn(user_text):
messages.append(
{"role": "user",
"content": user_text}
)
reply = client.messages.create(
model="claude-opus-5",
max_tokens=1024,
system=system, # state in
messages=messages,
)
return reply
# ... along the way ...
state["prefers"] = "metric units"
state["last_checkpoint"] = "step_4_done"
# session end: save
with open("state.json", "w") as f:
json.dump(state, f)
Концептуальна частына не вімагае нічого більшэ. Файл JSON вважаецца рэальною рэалізаціею; так само як і радок у базі даных, сховішчэ тыпу key-value або папка з нотаткамі у фарматы markdown. Серэдовішчэ ёсць другораднім елементом, а важліво тыя, хто вірышуе, што зберыгаты і што перэзавантажуваты.
Правільне прыйнятця гэтага рышэння ёсць складною частыною, і саме тут рызняцца фрэймворкі агентаў. Найпрамішый варыант перэдае задачы мадэлі: за допомогою інструменту памяці Anthropic Claude отрымуе невелікій набір команд для файлів (перэгляд, створэння, заміна, вставка, відалення і перэйменування), які працуюць у ізаляваній дырэкторыі /memories, тож агент вібірае, што заслуговуе на зберэжэння, і чытае ці нотаткі на початку наступноі сесіі. Ваш власній додаток віконуе операціі з будзь-якім обранім вамі сховішчэм. Інструмент працюе на стороні кліента, што дозволяе зберыгаты файлі у вашому контролі.
Адрэснае месца: праця ў спадчыну, персаналізацыя і давгастраўнае веданне. Агент, які працуе над багадзённым заданнем з таго моменту, калі ён стаў, патрабуе гэтага, так сама як і той, які не павінен два разы запытаць пра ваш часавой пояс.
Косты:
- Хтосьці трэба каратырацыя. Запісайце все, і вы створыце транскрыпцыю, якую нельзя будзе адшукаць. Калі запісаце занадта мало, праця ў спадчыну будзе наражана на перывантажэння. Хорашы стабільны стан важка атрымліваць.
- Старыя даныя горшы, чым ўсё жаданае. Прынцып, зберажаны восем месцаў таму і ніколі не пераглянуты, будзе застосоўвацца з аблігацыяй. Неудачы ў адшуканні прыносяць неяснасць, а стары стан — аблігацыйна некорэктную працю.
- Завантажэнне не ўжо безкоштовна. Што бы вы ні завантажылі, гэта ўсё равно займае прастор у вікні, таму Лейер 3 таксама падпірае Лейер 1.
Выкорыстоўваецца стан, які застаёцца незменным, калі той самы корыстнік або задача паўтараючыся запускае агента, і тое, што выучыў запуск n, павінна змяніць запуск n+1.
Тры падходы паўнаравнай
| Вікна кантэксту | Адзыскванне інфармацыі | Стан, які застаёцца незменным | |
|---|---|---|---|
| Ролі | Стол | Бібліятэка | Зошыт |
| Храніць | Усё, што ўключанае ў гэты запіт | Вялікі, спаканаваны корпус дадзеных | Маленькія факты, якія запісаў агент |
| Ствараецца | Я вашы прыкладнік, з кожным вызывамЗадача індэксавання | Агент або ваш код | |
| Застаёцца пасля перзапуску | Нята | Так | Так |
| Галоўны рызык | Косты, втрата інфармацыі | Пропуск частак дадзеных | Застарэлыя факты |
Найважлівейшыя радкі — тые, які стосуюцца перэзапуску. Яны ўтвараюць межу між довгай розмовай і агентам, які пам’ятаюць кантэкст.
Які методы вікорыстоўваюцца
Працявітэль, які робіць падтрымку, вікорыстоўвае ўсе тры методы, і корысна спаглядаць, як яны працуюць у рамках адной запіту. Агента пытаюць, чыі замовленні падпадае пад умовы продлжанага тэрміну вярнення.
- Спачатку завантажаецца персістэнтны стан: у гэтага кліента ёсць бізнес-план, і яму пасаблівыя короткія адказы. Два факты, працоўна гэта адпаведае або чатырнадцатым токенам.
- За дапамогою збору інформацыі аналізуецца запіт, і выкарыстоўваецца роздзіл з правіламі вярнення для бізнес-планаў, а таксама два найнявэльнейшыя выключэння. Гэта тры часткі інфармацыі, працоўна гэта адпаведае або дванастам тысячам токенам.
- Кантэкстны вікну аб’ёднае ўсё гэта, а таксама інформацыю з жывай розмовы і ваказанні інструментаў, і мадэль аналізуе всю інформацыю разам.
Адна запытка, тры слоі. Вікна — гэта тое, дзе ўсё знаходзіцца, тады як запрашэнне і пастойны стан — гэта два адналежны шляхі да яго.
Самэ гэтая прычына, чаму агентам, якія працуюць дзялей, зазвычай радзяць соўмешчаць памяць з рэдагаваннем кантэксту: старыя рэзультаты інструментаў адчышваюцца з вікна, ўбліжчаючы яго, а факты, якія варта зберагчы, вялікі час яшчэ былі захаваны, таму вікна застаецца маленькім без втраты знанняў.
Каторы з іх вам на самай працоўцы трэба?
Пачатківцы практычна завжды спачатку беруць базу дадзеных вектараў. Гэта найболей відчутны частка стака, але рэдкая развязка. Лепшая прабаваць падымацца па лесцы.
Пачніце з акна. Чы гэтыя всі неабходны элементы пасляюць у адной заявке за ценай, якая вам падабаецца? Як так, тады стойце. Ні індэкса, ні хранення.
Увядзіце інформацыю пра стан агента пасля таго, як ён запускаецца вдругой раз. Калі другая сесія павінна ведаць тое, што дазнала першая сесія, патрэбны слой 3, і файл JSON ёсць правільнай адпаведнасцю. Зрабіце гэта ўжо на пачатку працэса запрашэння; так будзе дэшава, проста і гэта самое тое, чаго насправды хочу большасць людзей, калі яны кажуць, што хочуць, каб агент іх памятаў.
Увядзіце функцыю запрашэння, калі корпус дакументаў большы за акно. Гэта значыць, што ёсць многа дакументаў, якія дзелююцца межу корыстнікамі і якія рэдагуюцца окрэма ад вашага коду. Гэта самы сложны слой для стварэння і паставання ў працу, таму прыемлівайце яго толькі тады, калі гэта стане неабходнасцю.
Адзін падступ, якога трэба ухіліцца: стварэнне каналу RAG для таго, што на самай працэ быў файл праганаў, а потым разбіранне прычыны, чаму агент усё рава забывае імя каго-небудзь. Функцыя пошуку перацьварае інфармацыю з корпусу, і ёй ніколі не будзе можна зберагчы той факт, што адныя людзі воліюць метрычныя едыніцы.
Короткая версія
- Вікна кантэксту: стол. Відразу відны, дорогі за кожны токен, і очышваюцца як толькі сесія завершаецца.
- Пошук інфармацыі: бібліятэка. Вялічзеная, з можлывасцю пошуку, апдэйтаваная за пазначаным графікам, і ўсё, што агент толькі чытае.
- Пастаяны стан: зошыт. Маленькі, запісваецца агентам, і ён — едыны слой, які пераносіць урокі сёння на завтра.
Сама мадэль нічога не зберагчыць. Так званая памяць — гэта інжынерны выбар, які прымецца зноў і зноў па кожнай запытке: што мае знаходзіцца ў гэтым вікні, і звядзе куды яго трэба прынясіць?
Для дальшага чытання паспэкты Anthropic працяўнікаў на тэму эфектывае інжынерыя кантэкста і стварэння эфектываўых агентаў, а таксама яе дасведчэнні пра інструменты для каштовання і рэдагавання кантэкста, дакладней раскрываюць гэтыя тэмы.