Файл, які мой агент чытае першым у кожнай сесіі, я завёў 11 жніўня. Цяпер у ім 934 радкі і за плячыма 83 каміты. Большасць з іх гэта мая папраўка, ператвораная ў правіла з датай і ўстаўленая туды, дзе здалося дарэчы. Калі агент прапусціў адно з гэтых правіл, першым я западозрыў месца, дзе яно ляжыць у файле. У галаве ў мяне быў графік з Lost in the Middle. Дакладнасць высокая на абодвух краях акна і правісае ў сярэдзіне. Я лічыў гэтую крывую ўласцівасцю моўных мадэляў наогул, але ні разу не праверыў яе на мадэлі, якую выклікаю кожны дзень.
Таму я ўзяў задачу з гэтага артыкула і прагнаў яе сам.
Стэнд
Liu і сааўтары (arXiv 2307.03172, TACL 2024) прыдумалі сінтэтычную задачу, якая мне падабаецца тым, што ёй зусім не патрэбныя разважанні. JSON-аб’ект з выпадковых пар ключа і значэння і пытанне пра адзін ключ. Форму я пакінуў, а ідэнтыфікатары скараціў да 8 шаснаццатковых знакаў, каб 200 пар змяшчаліся ў кантэкст мадэлі, якая круціцца на працэсары. Унутры аднаго памеру і аднаго зерня аб’ект адзін і той жа на ўсіх 11 глыбінях. Перамяшчаецца толькі спытаны ключ, ад першага радка да апошняга. Таму ўплыў глыбіні не змешваецца з уплывам іншага аб’екта.
Пасля аб’екта і ключа кожны выклік атрымлівае адну і тую ж інструкцыю:
Answer with the value only, 8 hex characters, nothing else. If the key is not in the object, answer NOT FOUND.
Галоўны тут другі сказ. У асобнай серыі пытаюцца пра ключ, якога ў аб’екце няма наогул. Там адзіны правільны адказ NOT FOUND. Без яўнага дазволу адмовіцца мадэль, якая ніколі не кажа, што не ведае, проста выконвала б маю інструкцыю.
Малыя мадэлі гэта Qwen2.5 0.5B Instruct у float32 і 1.5B Instruct у bfloat16, прагнае дэкадаванне, transformers 5.16.1 і torch 2.14.0 на 4 ядрах працэсара. Мадэль, якой я карыстаюся насамрэч, гэта claude-haiku-4-5. Я выклікаў яе праз Claude Code CLI без рэжыму разважанняў, без інструментаў і з пустым канфігам MCP. Над папкай не было ніводнага CLAUDE.md, бо CLI моўчкі падхоплівае гэты файл. Haiku дайшла да 6000 пар, гэта каля 96 тысяч токенаў промпту і прыкладна палова яе акна.
Гэта да мяне мералі шмат разоў. Needle in a haystack Камрадта і RULER (arXiv 2404.06654) высвятляюць, у якім месцы акна мадэль памыляецца. Zhang з сааўтарамі (arXiv 2605.23170) разбіраюць, з чаго складаюцца няправільныя адказы. NoLiMa (arXiv 2502.05167) паказала, што даслоўнае супастаўленне накшталт майго трымаецца на значна большай даўжыні, чым задачы, дзе патрэбны хоць адзін крок вываду. У справаздачы Context Rot ад Chroma, ліпень 2025, адзначана, што Claude Sonnet 4 і Opus 4 схільныя ўстрымлівацца ад адказу, калі не ўпэўненыя. Сам я хацеў праверыць 2 рэчы: наколькі далёка ад мэты трапляе промах і ці трымаецца адмова.
Крывая, якую я чакаў
Мадэль на 0.5B ламаецца ўжо на самым малым памеры: на 25 парах, 565 токенах, яна адказвае правільна толькі 45 разоў з 88. Але крывая не мае формы літары U. Калі скласці 4 памеры, апошні радок яна знаходзіць у 62.5 працэнта выпадкаў і ўсе астатнія глыбіні ніжэй, без правалу ў сярэдзіне. Мадэль на 1.5B адказвае правільна 90 разоў з 99. Яе промахі раскіданыя недзе паміж 30 і 80 працэнтамі глыбіні і пры 3 зернях на клетку формай я гэта назваць не магу.
Haiku адказала правільна 243 разы з 245 і 3 з гэтых выклікаў былі першай пробай на 100 парах. Абодва промахі на 6000 парах, адзін у сярэдзіне і адзін на 90 працэнтах. Ва ўсіх астатніх клетках на ўсіх памерах стаіць 100. Але першае, што мяне там здзівіла, было іншае. Канверт адказу паказвае 3 уваходныя токены для гэтых промптаў і нейкі час я думаў, што аб’ект да мадэлі не даходзіць наогул. Насамрэч увесь аб’ём улічваецца ў cache_creation_input_tokens.
Куды трапляе промах
Мадэль на 0.5B дала 253 няправільныя адказы і 227 з іх выглядаюць сапраўды як правільны: 8 шаснаццатковых знакаў і нічога больш. Толькі 24 разы яна адказала NOT FOUND на ключ, які ў аб’екце быў. 71 раз замест значэння прыйшоў ключ, у 65 выпадках нейкі іншы ключ з аб’екта. 140 разоў прыйшло іншае значэнне з таго ж аб’екта і я паглядзеў, наколькі далёка ад мэты яно ляжыць. Пры роўнамерным выбары сярод астатніх радкоў 3.5 працэнта такіх значэнняў прыйшлі б з радка, непасрэдна суседняга з мэтай. Выйшла 16.4 працэнта і часцей за любы іншы радок мадэль брала той, што стаіць адразу пасля мэты. Медыяна адлегласці 7 радкоў супраць 36 пры роўнамерным выбары. Гэта значыць, няправільныя значэнні ў яе прыходзяць у асноўным з радкоў побач з патрэбным, але не з яго самога. Промахаў у haiku ўсяго 2, гэтага замала, каб нешта сказаць.
Ключ, якога не было
А вось тут haiku паводзіць сябе інакш. Да 2000 пар, каля 32 тысяч токенаў, яна адказала NOT FOUND 40 разоў з 40. Далей доля падае з ростам памеру, да 8 з 20 на 6000 парах. Астатнія 12 адказаў на 6000 былі па 8 шаснаццатковых знакаў: 8 значэнняў з аб’екта і 4, якіх у ім няма нідзе. Код, які выклікаў мадэль, ніяк не можа ўбачыць, што гэта здагадка.
Некаторыя адказы парушылі “value only” і дадалі тэкст. Гэты з серыі на 3000 пар:
Looking through the provided JSON object, I can find:
"7c98d2eb": "69e27874"
69e27874
Ключа 7c98d2eb у гэтым аб’екце няма. 69e27874 гэта значэнне з яго апошняга радка. Мадэль працытавала радок, якога не існуе, складзены са спытанага мной ключа і значэння з канца промпту. У серыях на 3000 і 4000 пар такіх адказаў з тэкстам вакол было 17. 13 з іх заканчваліся словамі NOT FOUND і 4 працытавалі радок, якога няма. Астатнія няправільныя адказы ў гэтых серыях былі голым шаснаццатковым значэннем.
У сетцы даўжыня і колькасць ключоў растуць разам, так што прычынай можа быць любое з двух. Кантроль гэта 1000 пар, перад якімі стаіць проза без адзінага шаснаццатковага слова, усяго каля 82 тысяч токенаў. Гэта даўжэй за промпт на 4000 пар, дзе з 20 адмоў ужо зніклі 5. NOT FOUND прыйшоў 10 разоў з 10, а з ключом, які ў аб’екце ёсць, адказ быў правільным 5 разоў з 5. Значыць, на гэтай задачы адна толькі даўжыня адмову не зламала, прынамсі калі даўжыня стаіць перад дадзенымі. Больш падазроная тут колькасць падобных ключоў. Кантроль маленькі, усяго 15 выклікаў. Малыя мадэлі тут не дапамагаюць ні ў які бок. 0.5B адказала NOT FOUND 8 разоў з 80 на аб’ектах ад 25 да 200 пар, а 1.5B 24 разы з 24 да 100 пар.
Чаго я не правяраў
Задача адна, прычым на даслоўны пошук. Правіла з майго файла, якое агент прапусціў, гэта пытанне выканання інструкцыі. NoLiMa дае добрую падставу думаць, што выкананне інструкцый ламаецца раней за пошук шаснаццатковага радка, так што гэта не даказвае, што з файлам усё ў парадку. Замер толькі прыбірае самае простае тлумачэнне. Haiku налічвае ў файле каля 25 тысяч токенаў, менш за 32 тысячы, на якіх яна адмаўлялася кожны раз, калі ключа не было. Але ў сапраўднай сесіі файл ляжыць унутры значна большага кантэксту побач з сістэмным промптам і перапіскай.
З мадэляў праз API тут толькі haiku і далей за 96 тысяч токенаў я не заходзіў. У радках на 500 і 2000 пар толькі 3 зерні на глыбіню, у радках на 4000 і 6000 іх 8. 2 мадэлі Qwen ішлі з рознай разраднасцю і ці ўплывае гэта, я не правяраў.
З гэтага я выношу адно: праверку ў кодзе. Значэнне, якое вярнулася з вялікай табліцы, трэба зноў знайсці ў гэтай табліцы, па тым ключы, пра які пыталіся. Праверкі, што такое значэнне там наогул ёсць, мала: выдуманы радок вышэй яе прайшоў бы. Выклікі haiku, на якіх трымаюцца гэтыя лікі, каштавалі прыкладна 45 даляраў.