Drastické snížení nákladů na inferenci o 68 % díky důsledné optimalizaci

Náš systém pro automatickou revizi kódu čelil prudkému nárůstu provozních nákladů, což si vyžádalo komplexní optimalizační snahy. Díky cíleným úpravám se nám podařilo snížit náklady na jednu revizi o 68 % a zároveň výrazně zkrátit dobu zpracování.

Drastické snížení nákladů na inferenci o 68 % díky důsledné optimalizaci

V nedávné době jsme zaznamenali významný nárůst provozních nákladů našeho nástroje pro automatickou revizi kódu. Zatímco v dubnu stála průměrná revize přijatelných 1,19 USD, koncem srpna tato hodnota vystřelila až na přibližně 2,46 USD. V té době nedošlo k žádným zásadním architektonickým změnám, přesto náklady rostly. Koncem září jsme se proto intenzivně zaměřili na analýzu spotřeby tokenů a jejich agresivní snižování. Dnes, při vysokém úsilí o kvalitu kódu, stojí průměrná revize pouhých 0,77 USD, což představuje 68% pokles oproti průměrným 2,43 USD, které jsme platili v našich dvou nejdražších týdnech před zahájením optimalizace. Hlavním cílem bylo snížit náklady, ale jako vedlejší produkt této práce se nám podařilo optimalizovat i rychlost recenzování, takže mediánová doba revize nyní trvá jen 1 minutu a 32 sekund, namísto původních 4 minut a 9 sekund. Přibližně 40 % úspor pochází ze změn a optimalizací v kódu samotného revizora, zbytek pak z experimentování s použitými modely a úrovněmi úsilí, které do revize vkládají.

Analýza ukázala, že náklady na jednu revizi neustále rostly: z 1,22 USD v březnu na 1,44 USD v červnu, 1,74 USD v červenci a nakonec 2,32 USD v srpnu. Malou část tohoto nárůstu lze přičíst tomu, že více revizí spadalo do nejdražší kategorie (z 59 % v březnu na 65 % v srpnu). Předpokládáme, že důvodem je neustálé zlepšování a schopnosti jazykových modelů, což vede inženýry k vytváření větších a komplexnějších změn, které pak častěji vyžadují „úplnou revizi“. Nicméně, většinu nárůstu nákladů způsobily změny v modelech. Počátkem srpna jsme převedli všechny revizory na modely Anthropic, což zvýšilo náklady na úlohu z 1,38 USD na 2,03 USD. Toto rozhodnutí bylo podloženo tím, že modely Anthropic v našich hodnoceních vykazovaly lepší výkon pro specifické pracovní zatížení. Náš interní revizor standardů, původně pracující s modelem Codex, skončil na modelu Claude Opus 4.7 kvůli kombinaci výkonu a spolehlivosti. To zvýšilo jeho náklady z přibližně 0,25 USD na 0,88 USD za revizi v srpnu, čímž se stal dražším než samotný koordinační agent. Zároveň se zvýšila míra zásahů do cache z 85,7 % v dubnu na 97 % v září, zatímco počet tokenů na revizi se více než ztrojnásobil, z 0,91 milionu na 2,99 milionu. Vysoká míra zásahů na trojnásobném objemu tokenů stále znamená výrazně vyšší náklady, a to i přes nízké náklady na čtení z cache.

Jednou z největších změn je, že revizor nyní běží na OpenCode v2, což je kompletní přepsání původní verze. Před plným přechodem všech revizí z v1 na v2 jsme paralelně spouštěli každou revizi v obou verzích v porovnávacím stínovém režimu. Obě verze se shodly na schvalovacím rozhodnutí v 98 % testovaných požadavků na sloučení, takže jsme na začátku října převedli všechny uživatele najednou a kód v1 odstranili. Při srovnání dvou dnů se stejnými modely dokončí plnotřídní revize na v2 přibližně o 13 % rychleji. Současně experimentujeme s dalšími způsoby, jak provozovat naše interní AI řešení, včetně výhradního využití Durable Objects. Očekáváme, že brzy budeme mít k dispozici další informace.

Před zahájením optimalizace nákladů byly výdaje na AI revize rozděleny takto: výstupní tokeny tvořily přibližně 23 %, náklady na zápisy do cache 43 % a čtení z cache 34 %. To znamená, že většina peněz směřovala do kontextu, který model již viděl nebo brzy znovu uvidí. To dává smysl, když se podíváme na jedinou relaci. Revizor kvality kódu provedl v průměru 16,6 volání velkých jazykových modelů (LLM) na revizi a během těchto volání zapsal 72 tisíc tokenů do cache a přečetl zpět 1,08 milionu, protože každé volání odesílá celou konverzaci jako kontext. Náklady relace rostou s počtem volání i s velikostí kontextu, a v posledních měsících jsme pomalu zvyšovali obojí.

Je důležité porozumět, jak funguje cache promptů v modelech Anthropic. Funguje tak, že ukládá do cache části promptu, které již byly zpracovány velkým jazykovým modelem (LLM). Tyto části jsou známé jako prefixy, protože fungují pouze na zprávy na začátku konverzace, nikoli uprostřed nebo na konci. To znamená, že budoucí požadavek může znovu použít dřívější prefix, až do té části konverzace, která se liší od toho, co bylo uloženo v cache. V našem případě se nástroje, systémový prompt a zprávy na začátku našich revizních relací mění jen zřídka, takže jsou ideálním kandidátem pro cachování prefixů. Prefix je uložen pouze tam, kde jej ukončuje bod přerušení cache. Zápis do cache stojí 1,25násobek běžné vstupní ceny a čtení stojí 0,1násobek, a záznam vyprší po pěti minutách, pokud jej nic nepřečte. To znamenalo, že jsme měli pracovat na dvou věcech: zajistit, aby první požadavek každé relace četl z cache namísto do ní psal, a zajistit, aby každá relace používala méně volání.

Dominik Medal

Chystáte nový web nebo aplikaci?

Napište mi, co plánujete — rád se na to podívám a poradím, jak na to nejlépe jít.

Od 14. září systém zaznamenával spotřebu tokenů prvního volání LLM každého revizora a hash prvního systémového bloku přesně tak, jak byl odeslán poskytovateli. Data ukázala, že první požadavek relace našel cachovaný prefix pouze ve 14 % až 26 % případů. Každá relace začíná stejnými definicemi nástrojů a stejným agentním promptem, což je mezi 11 tisíci a 21 tisíci tokeny, které jsou identické v každém repozitáři, který revidujeme. Téměř všechny by tedy měly být zásahy do cache. Problém spočíval v tom, jak OpenCode v1 konstruoval systémový prompt: vytvořil jeden blok obsahující náš agentní prompt, následovaný sekcí prostředí s pracovním adresářem a datem, a jediný bod přerušení cache umístil na konec tohoto bloku. Sdílená část nebyla nikdy uložena samostatně, takže revize v jednom repozitáři nemohla nikdy znovu použít to, co zapsal revizor spuštěný v jiném repozitáři. Dne 16. září jsme přidali značku na konec každého agentního promptu a plugin hook, který rozdělil blok na dvě části u této značky. První polovina nyní končí na bajtech, které sdílí každá úloha, a získala svůj vlastní bod přerušení. Abychom to tak udrželi, museli jsme z jejího začátku odstranit vše specifické pro repozitář, takže seznam dostupných dovedností je zakázán a popisy nástrojů se nemohou mezi úlohami měnit. Ve stejný den jsme také přesunuli referenční index (tabulka interních standardů, soubor dovedností a seznam referenčních souborů) našeho interního revizora standardů (Codex) do jeho promptu. Do té doby každá relace strávila první tři tahy čtením těchto souborů pomocí volání nástrojů. Počet jeho volání LLM na spuštění se snížil z 15,9 na 9,6 a jeho náklady na spuštění klesly z 1,12 USD na 0,72 USD. Tyto změny dohromady snížily náklady na revizi z 2,47 USD na 2,02 USD a pokles byl znatelný ihned po nasazení.

Další soubor změn byl nasazen 21. a 23. září. Žádná z nich nebyla sama o sobě nijak zvlášť působivá, ale dohromady ušetřily přibližně 0,20 USD na každé revizi. Byly odstraněny nástroje, které revizor nemohl použít. Například dílčí revizoři viděli nástroj, který zveřejňuje závěrečný komentář k revizi. V 57 % až 76 % relací se jej pokusili zavolat, byli zamítnuti kontrolou na serveru a strávili další volání na zotavení, což znamenalo jedno zbytečné volání a přibližně 2,9 tisíce méně tokenů definic nástrojů v každém požadavku. Dále se začalo číst soubory paralelně. V 64 % tahů revizora kvality kódu model provedl přesně jedno volání nástroje, obvykle pro čtení jediného souboru. Nyní revizoři čtou sdílený kontext a všechny své patche již v první odpovědi, až do 150 KB. Při opakovaných revizích, kdy asi dvě třetiny našich úloh jsou druhou nebo pozdější revizí stejného požadavku na sloučení a často tři revizoři nemají nic nového k prohlédnutí, jsou nyní u plnotřídních opakovaných revizí recenze AGENTS.md přeskočeny v 56 % případů, recenze výkonu v 23 % a recenze dokumentace v 13 %. Systém se nyní také zastaví po zveřejnění revize. Předtím systém předával výsledek zpět modelu na další tah, který znovu četl celou konverzaci, aby napsal souhrn, který nikdo neviděl, čímž se ušetřilo asi 0,07 USD na úlohu. Zlepšilo se i zacházení s pomalými revizory od selhání poskytovatele. Revizor, který narazil na svůj časový limit, byl dříve považován za selhání poskytovatele a začal znovu se stejným časovým limitem. Spolu s delšími časovými limity a nižším úsilím klesly časové limity bezpečnostního revizora z 1,8 % spuštění na téměř žádné. Navíc se začaly rušit zrušené úlohy. Kubernetes executor neodesílá signál skriptu úlohy, když je úloha zrušena. Ve vzorku 446 zrušených úloh 358 pokračovalo v běhu, dokud nebyla revize dokončena. Nyní úlohy kontrolují svůj vlastní stav každých 15 sekund a zastaví se, pokud jsou zrušeny. Nejkomplexnější změnou bylo sdílení jednoho prefixu mezi třemi revizory. Revizoři kvality kódu, bezpečnosti a výkonu nyní odesílají identické první požadavky se stejnými nástroji, sdíleným souborem pravidel a poté požadavkem na sloučení s každým patchem. Návod pro každého revizora následuje poté, a zajišťujeme, aby jeden z nich zapisoval do cache a ostatní dva z ní četli. Záznam v cache nelze přečíst, dokud odpověď, která jej zapsala, nezačala streamovat, a tři revizoři začínají současně. Takže druhý a třetí čekají na zahájení odpovědi prvního, až 20 sekund, než odešlou svůj vlastní první požadavek. To je mírně zpomaluje a ušetří asi devět centů na revizora.

Kódové změny tvořily menší část celkové úspory (0,65 USD z 1,67 USD), zatímco změny modelů a úsilí přispěly 1,06 USD. Bylo ověřeno, že plnotřídní úlohy se středním úsilím dokončily o 20 % dříve, takže jsme upustili od ostatních dvou kombinací. Při pozdějším randomizovaném dělení neukázala verze Opus 5.5 se středním úsilím žádnou měřitelnou změnu ve výsledcích revizí nebo kritických nálezech ve srovnání s Opus 5, proto jsme na ni přešli. Opus 5.5 s vysokým úsilím stál více než Opus 5.5 se středním úsilím, aniž by přinesl smysluplné zvýšení počtu nálezů. Opus 5.5 je na token levnější než Opus 5, ale cena je zodpovědná jen za přibližně 0,20 USD z poklesu. Zbytek pochází z odesílání a generování méně tokenů. Od začátku září klesly čtení z cache na revizi o 82 %, zápisy do cache o 54 % a výstup o 67 %. Nejnovější změnou byl nový model. 3. října jsme rozdělili všechny revizory Sonnet 50/50 mezi Sonnet 5 a Sonnet 5.5. Po dvou a půl dnech byl Sonnet 5.5 o 62 % levnější na spuštění pro kvalitu kódu, o 58 % pro výkon a o 47 % pro bezpečnost. Oba modely stály stejně za token, takže veškerá úspora pochází z použití méně tokenů. U plnotřídních revizí revizoři 5.5 zveřejnili zhruba stejný počet kritických a varovných nálezů jako ti s Sonnet 5, takže 5. října jsme je všechny převedli na 5.5. S modelem Sonnet 5.5 se středním úsilím provede revizor kvality kódu 1,7 volání LLM na spuštění namísto 6,2, a více než polovina jeho spuštění dokončí v jediném volání, což znamená, že neotevře žádný další soubor v repozitáři. S vysokým úsilím provede 3,4 volání na spuštění. Byla obava, že to revize zplošťuje, což je pokryto v sekci kvality níže. Abychom zjistili, zda větší úsilí přináší nálezy zpět na větších úrovních, je revizor kvality kódu rozdělen 50/50 mezi střední a vysoké úsilí na 5.5 od 5. října. Po jednom dni stojí vysoké úsilí o 61 % více na spuštění a zveřejňuje o 58 % více kritických a varovných nálezů. To je přibližně dva centy na revizi, a sekce kvality níže ukazuje, že tyto dodatečné nálezy stojí za to, takže přecházíme kvalitu kódu na vysoké úsilí. Náklady v tomto příspěvku s tím počítají.

Zkrácení doby revizí nebylo primárním cílem, ale méně volání znamená také méně čekání, což se promítá do rychlejších revizí a spokojenějších inženýrů. Nejpomalejší revize se zlepšily nejvíce. V průběhu čtyř týdnů před 14. zářím trvalo 37,9 % revizí déle než pět minut, zatímco nyní je to jen 0,7 %. Dnes je 99. percentil rychlejší než tři čtvrtiny revizí v dubnu. Každá kategorie se postupně zrychlila, přičemž mediánová plnotřídní revize se snížila z 5 minut a 16 sekund na 1 minutu a 54 sekund, lehká revize z 2 minut a 58 sekund na 1 minutu a 14 sekund a triviální revize ze 77 sekund na 30 sekund. Do srpna byla mediánová doba revize o 14 % pomalejší než v dubnu a 99. percentil o 48 % pomalejší, takže velká část této práce nás pouze vrátila tam, kde jsme již byli.

Levnější revize by neměla velkou hodnotu, pokud by zároveň nacházela méně problémů. Zpočátku se zdálo, že s kvalitou kódu na modelu Sonnet 5.5 s vysokým úsilím systém hlásí o 40 % méně kritických a varovných nálezů než koncem srpna. Revizoři bezpečnosti a výkonu, kteří zůstali na středním úsilí, hlásili o 56 % a 71 % méně. Pokles závažných nálezů sám o sobě neřekne, zda jsou přehlédnuty skutečné problémy, nebo zda je pouze odstraněn šum. Proto jsme to zkoumali ze dvou úhlů. Nejprve jsme ověřili, zda autoři reagují na to, co systém označí. U vzorků kritických a varovných nálezů jsme porovnali revidovaný commit s dalším pushem autora a nález jsme považovali za vyřešený, pokud se změny týkaly označených řádků. Řádky 30 až 40 od každého nálezu se změnily přibližně v 15 % případů v každém období, což slouží jako základ pro náhodné úpravy. Před změnami autoři reagovali na 34 % závažných nálezů revizora kvality kódu. Nyní je to 59 %. Revizor označuje méně věcí, ale ty, které označí, s mnohem větší pravděpodobností vedou ke změně, takže počet nálezů, které vedly ke změně na 1 000 revizí, je zhruba stejný (132 oproti 145 dříve, což je v mezích chyby). Napříč všemi čtyřmi revizory se závažné nálezy, které vedly ke změně, zvýšily z 229 na 321 na 1 000 revizí. Zadruhé, nechali jsme dva modely od různých poskytovatelů posoudit zaslepený vzorek 657 nálezů od tří revizorů Sonnet, s diffem, na který se každý z nich odkazoval, a bez znalosti, ze kterého období pocházel. Nesrovnalosti byly předány třetímu modelu. Každý nález byl označen jako důležitý, drobný, duplicitní, chybný nebo neověřitelný, a jeho závažnost byla označena jako spravedlivá, příliš vysoká nebo příliš nízká. Většina zmizelých nálezů byly drobné nálezy, plus některé duplikáty a nálezy, které hodnotitelé nemohli ověřit z diffu. Důležité nálezy na revizi se zvýšily z 0,28 dříve na 0,30 nyní a intervaly se překrývají. Větší změna nastala v závažnosti. Dříve hodnotitelé hodnotili 0,46 kritických nebo varovných nálezů na revizi jako závažnější, než si zasloužily. Nyní je to 0,14, což je pokles o 70 % a nejjasnější výsledek výzkumu. Velká část poklesu kritických nálezů je způsobena tím, že revizor již neoznačuje drobné věci jako kritické.

Odpověď na otázku kvality tak závisí na konkrétním revizorovi. Pro kvalitu kódu s vysokým úsilím zmizel převážně šum a přehnaná závažnost, a systém stále nachází zhruba stejný počet skutečných problémů jako dříve. Střední úsilí však skutečné nálezy ztrácelo. Při randomizovaném rozdělení vedla kvalita kódu se středním úsilím k zhruba čtvrtině nálezů, na které se reagovalo, ve srovnání s vysokým úsilím, což je důvod, proč ji přesouváme na vysoké úsilí. Také výkon ztratil skutečné nálezy: hodnotitelé zjistili přibližně o 64 % méně důležitých problémů s výkonem na revizi, což v praxi znamená zhruba jeden důležitý nález méně na každých 24 plnotřídních revizí. Bezpečnost klesla o přibližně čtvrtinu, ačkoli to není statisticky významné. Obě tyto kategorie zůstávají na středním úsilí a jejich testování na vysokém úsilí je dalším krokem. Žádná z metod není dokonalá. Změna označených řádků autorem ukazuje, že něco udělal, nikoli že nález byl správný. Hodnotitelé jsou také modely a v každé skupině je jen 35 až 66 nálezů. I tak se obě metody shodují a žádná z nich nenaznačuje, že by kvalita kódu nacházela méně skutečných problémů. Spolehlivost se rovněž udržela. Revize, které končí bez verdiktu, klesly z 0,79 % na 0,27 % a opakované pokusy bezpečnostního revizora z 3,5 % na 0,04 %.

Průměrná revize nyní stojí 0,77 USD namísto 2,43 USD a mediánová revize se dokončí za 1 minutu a 32 sekund namísto 4 minut a 9 sekund. Největší jednotlivá úspora pocházela z kontroly toho, co skutečně dosáhlo poskytovatele při prvním požadavku každé relace, a nalezení způsobu, jak tyto zprávy uspořádat co nejkonzistentněji napříč commity, merge requesty a repozitáři. Zbývající úspory nákladů pocházely z neúnavného experimentování s různými modely a kombinacemi úsilí, přičemž jsme dbali na to, abychom odložili veškeré předpojatosti vůči konkrétním modelům. Levnější revize automaticky neznamenaly horší kvalitu, ale ani to automaticky neznamenalo, že je vše v pořádku. Kvalita kódu s vysokým úsilím nachází zhruba stejný počet skutečných problémů jako dříve, s mnohem menším šumem a daleko menším počtem přehnaných závažností. Výkon ztratil skutečné nálezy při středním úsilí a bezpečnost možná také, takže testování obou s vysokým úsilím je dalším krokem. Pokud provozujete automatizované agenty v jakémkoli objemu, dvě věci, které bychom nejprve zkontrolovali, jsou, zda první požadavek každé relace skutečně čte z cache, a zda vaši revizoři stále nacházejí skutečné problémy na úrovni úsilí, za které platíte.

Dominik Medal

Popovídejme si o Vašem projektu

Napište mi, co potřebujete, a společně určíme nejlepší postup.

Už nescrollujte, volejte

+420 735 505 585