Калі мяне пытаюцца, дзе месца моўнай мадэлі побач з грашыма, я адказваю адным сказам. Вынікі лічыць дэтэрмінаваны рухавік, а мадэль толькі пра іх распавядае. 8 кастрычніка я памераў прагнозную палову гэтага падзелу. Палову з рахункамі я не мераў ніколі, проста паўтараў, таму на гэты раз узяў рахунак.
Пастаноўка
Я жыву ў Варшаве, таму рахунак польскі, з VAT. У кожным радку колькасць, цана нета за адзінку ў злотых, зніжка і стаўка VAT 23, 8, 5 або 0 працэнтаў. Правіла напісана ў задачы. Нета кожнага радка акругляецца да гроша, паўгроша ўверх. Потым радкі групуюцца па стаўцы, VAT бярэцца ад сумы кожнай групы і зноў акругляецца. Брута роўнае нета плюс VAT.
Рухавік гэта каля 20 радкоў на Python 3.12.3 з decimal і ROUND_HALF_UP. 10 000 рахункаў па 40 радкоў ён лічыць ад 0,83 да 1,18 секунды, прыкладна 0,1 мс на рахунак. 3 паўторы даюць адзін і той жа хэш усіх вынікаў.
Мадэль гэта claude-opus-5 праз Claude Code 2.1.292. Запускаў я яе з пустога каталога без інструментаў і без сервераў MCP. З фіксаваным зернем я згенераваў 10 рахункаў па 5 радкоў, 10 па 15 і 10 па 40. Кожны рахунак пайшоў мадэлі 2 разы. Адказ павінен быў быць адным радком JSON з 3 вынікамі. Супадзеннем лічыцца, калі нета, VAT і брута ўсе да гроша супадаюць з рухавіком.
Да падліку я запісаў, чаго чакаю. На 5 радках мадэль дакладная хаця б у 9 выпадках з 10. На 40 радках яна дакладная менш чым у 7 з 10 і 2 прагоны аднаго рахунку хаця б раз разыходзяцца.
Думка, што код лічыць лепш за мадэль, старая і не мая. PAL і Program of Thoughts у 2022 годзе вынеслі арыфметыку з мадэлі ў праграму. Я проста ні разу не бачыў гэтага на рахунку.
Маленькія рахункі
На 5 радках мадэль была дакладная 9 разоў у кожным прагоне. На 15 радках яна была дакладная 9 і 10 разоў. Промахі былі невялікія. Адзін рахунак разышоўся на 5 грошаў, другі на 85. Трэці разышоўся акурат на 1,00 злотага нета. VAT ад гэтага зрушыўся на 8 грошаў.
Больш за памер мяне турбуе тое, што кожны няправільны адказ сыходзіцца сам з сабой. Нета плюс VAT ва ўсіх роўнае брута да гроша. Першая праверка, якую я б напісаў, складае 3 вынікі. Кожны з гэтых адказаў яе праходзіць.
40 радкоў і адказ, якога я не прасіў
На 40 радках я атрымаў 2 адказы JSON з 20. Абодва былі дакладныя. Астатнія 18 аказаліся праграмай на Python з Decimal. Частка прыйшла блокам кода bash, частка выклікам інструмента Bash, якога ў мадэлі не было. Такога я ўвогуле не планаваў. Таму я спыніўся і да далейшага падліку запісаў новае правіла: выняць кожную праграму з адказу і запусціць.
Усяго такіх праграм набралася 19, тут 18 і яшчэ адна з іншай часткі доследу. Кожную я запусціў праз python3 -I у пустым часовым каталогу. Усе 19 надрукавалі правільныя вынікі да гроша.
Потым я дачытаў адказы да канца. У 10 з 19 мадэль не спынілася на праграме і сама напісала вывад інструмента. 9 разоў гэта былі лікі, 3 з іх пад загалоўкам Tool Result. Адзін раз проста <redacted>. Ніводзін з 9 не супаў ні з правільнымі вынікамі, ні нават з тым, што друкуе яе ўласная праграма. На адным рахунку праграма друкуе нета 739 434,56, а выдуманы вывад пад ёй кажа 58 923,85. Іншы рахунак атрымаў у 2 прагонах 2 розныя выдуманыя вывады, 995 552,96 і 1 304 665,13, пры правільным нета 962 434,28.
Нейкі час я думаў, што ў 9 з гэтых адказаў кода няма ўвогуле. Мой першы скрыпт, які выцягваў праграмы, знайшоў іх толькі ў 10 з 19, а астатнія пазначыў як “кода няма”. Мадэль загарнула адну і тую ж праграму ў 3 розныя фарматы, а я не чакаў больш за адзін.
Лічыць уручную
Тады я адправіў тыя ж 10 рахункаў па 40 радкоў яшчэ 2 разы, дадаўшы ў задачу адзін сказ: “You have no tools and cannot run code. Compute the totals yourself.” Гэта значыць, інструментаў няма, код запусціць нельга, лічы сам.
Мадэль была дакладная ў 10 з 10 у першым прагоне і ў 9 з 10 у другім. Мая здагадка пра менш чым 7 не пацвердзілася. І адзіны промах таксама не пра акругленне. Мадэль цалкам прапусціла радок 27, 40 штук па 2462,10 са зніжкай 15%, таму нета меншае на 83 711,40, а VAT на 19 253,63.
Медыянны выклік заняў 42,9 секунды і каштаваў $0,11, на разважанне пайшло каля 4000 токенаў. На 5 радках гэта было 13,6 секунды і $0,024. Рухавік лічыць той жа рахунак з 40 радкоў прыкладна за 0,1 мс. Усе 100 выклікаў гэтага замеру каштавалі $5,71.
Калі правіла не названа
Другая мая здагадка была пра акругленне. Я даў 10 рахункаў па 15 радкоў без правіла, толькі “да гроша”. Я чакаў, што мадэль будзе пераскокваць паміж акругленнем VAT у кожным радку, па стаўцы або толькі ў самым канцы.
Яна не пераскоквала. 18 адказаў з 20 былі лікамі і ўсе 18 супадаюць з VAT ад сумы па стаўцы. Акругленне па радках і па стаўцы дае розныя вынікі ў 4 з гэтых 10 рахункаў. У гэтых 4 мадэль абодва разы выбрала акругленне па стаўцы. У адным адказе яна назвала гэта “standard Polish practice”, стандартнай польскай практыкай. Астатнія 2 адказы былі планам і праграмай. Праграма таксама аказалася правільнай.
Што я з гэтага вынес
Я ўжо быў гатовы напісаць, што мадэль не ўмее лічыць рахунак. Умее, у 19 выпадках з 20 на 40 радках, калі ёй загадана лічыць самой. Яе код быў правільны кожны раз. Няправільны вынік, які ўсё роўна сыходзіцца, праходзіць маю першую праверку. Вывад інструмента, які ніхто не запускаў, выглядае як доказ, хоць ім не з’яўляецца. Таму мае вынікі па-ранейшаму лічыць код на Decimal.
Чаго я не правяраў
Я праверыў 1 мадэль па 2 прагоны на рахунак і рахункі сінтэтычныя. Не было карэкцыйных рахункаў і замежнай валюты, нічога не сканавалася з паперы. Сапраўднага інструмента мадэль так і не атрымала, таму я ведаю, што яе праграмы правільныя, але не ведаю, што яна робіць з сапраўдным вынікам. Бюджэт разважання я сам не задаваў і само разважанне не чытаў, так што дзе згубіўся радок 27, я не ведаю.