Z.ai přijal přepis šablony GLM-5.3, která u stovek volání nástrojů počítala kvadraticky
Šablona, která u GLM-5.3 skládá dotaz z historie chatu, přiřazovala výsledky nástrojů k jejich voláním vnořenými cykly. Při osmi stech paralelních voláních v jednom tahu trvalo vykreslení 7,8 sekundy. Z.ai přepis přijal 14. října 2026, pět týdnů poté, co sám napsal, že tolik volání model stejně nevydá.
Z.ai začlenila 14. října 2026 do repozitáře modelu GLM-5.3 na Hugging Face návrh změny #31, který přepisuje kus šablony chatu. Den nato putovala táž úprava do repozitářů GLM-5.3-Flash a do obou variant s vahami v BF16. Jde o jediný blok v jediném souboru, zato o ten, kterým prochází každý agentní tah modelu.

Co šablona dělala u každého výsledku znovu
Šablona chatu je kus kódu v jazyce Jinja, který z posloupnosti zpráv – systémový pokyn, dotazy uživatele, odpovědi modelu, výstupy nástrojů – poskládá jeden text pro model. U agentních modelů v ní bývá nejsložitější právě část o nástrojích: model vydá několik volání naráz, výsledky se mu vracejí v libovolném pořadí a šablona je musí srovnat zpátky do pořadí volání.
GLM-5.3 to dělal vnořenými cykly. U každého výsledku se volala dvě makra, která pokaždé projela celý blok zpráv: jedno hledalo, jestli se totéž id neobjevuje dvakrát, druhé, jestli k němu vůbec existuje volání. Identifikátory volání se pak porovnávaly každý s každým. A nakonec se pro každé volání ještě jednou prošel celý blok, aby se k němu našel jeho výsledek. Autor návrhu to shrnul na zhruba 4 × N² volání maker pro N souběžných nástrojů v jednom tahu.
Čas vykreslení tím roste s druhou mocninou počtu volání. Naměřil ho Maroon Ayoub na jednom jádru procesoru Apple M4, s knihovnami transformers 5.19.0 a jinja2 3.1.6:
| Paralelní volání nástrojů | Před | Po |
|---|---|---|
| 100 | 0,13 s | 0,004 s |
| 400 | 1,95 s | 0,015 s |
| 800 | 7,81 s | 0,034 s |
| 1 200 | neuvedeno | 0,057 s |
Na serverovém jádře Sapphire Rapids vyšlo osm set volání podle téhož popisu zhruba na 13 sekund. Nad 1 200 voláními prý vykreslení přeteče výchozí třicetisekundový strop ve vLLM a opuštěné vlákno drží procesor serveru dál, takže se zpozdí i cizí požadavky. To měření ani ten popis nikdo nezávisle nezopakoval; jsou to čísla autora opravy.
Pět týdnů předtím to Z.ai označila za okrajové
Na tutéž vadu upozornil už 29. srpna 2026 návrh v inferenčním serveru SGLang. Jeho autor Kyle Flansburg nenavrhoval měnit šablonu, ale obejít ji: SGLang by vadnou verzi poznal podle otisku souboru a výsledky by si spároval sám v Pythonu. Jako důvod uvedl, že SGLang vykresluje šablonu přímo ve smyčce tokenizéru, takže dlouhá agentní historie zdrží i kontroly běhu a přijímání nesouvisejících požadavků.
Odpověď od Z.ai přišla 4. září a zněla v překladu takto: „Máte pravdu, že kontrola, jestli se po sobě jdoucí výsledky nástrojů musí přeskládat, je O(n²). V praxi ale model skoro nikdy nevydá velké množství paralelních volání nástrojů, takže n zůstává malé.“ Firma zároveň slíbila do šablony doplnit předčasné ukončení cyklu, jakmile se ukáže, že přeskládat nejde – a téhož dne to udělala. Vnořené cykly tím zůstaly, jen se dřív opouštěly při chybě.
Návrh v SGLangu pak ležel beze změny a 8. října ho zavřel automat s odůvodněním, že je to pořád koncept a 33 dní se v něm nic nestalo. Nikdo ho tedy neposoudil a neodmítl.
První verze opravy padala v jiném rendereru
Ayoub otevřel svůj návrh 13. října. Jeho první podoba posbírala identifikátory do dvou seznamů, zkontrolovala je filtrem unique a k dohledání pozice použila metodu index. Recenzent Z.ai namítl, že index je pythonovská vlastnost, kterou renderery psané v Rustu – jmenovitě MiniJinja, na které stojí Dynamo od Nvidie – neumějí ani v režimu kompatibility.
Ayoub to ověřil a potvrdil: pod Dynamem skončila každá konverzace s přeskládávaným blokem hláškou unknown method: iterator has no method named index. Náhrada, kterou recenzent navrhl – obyčejná smyčka –, by sice prošla, jenže by vrátila průchod seznamem u každého volání, a s ním kvadratický růst. Pod MiniJinjou by pak byla pomalejší než stávající stav: 2,9 s proti 1,3 s při osmi stech voláních a 13,9 s proti 3,0 s při dvanácti stech.
Přijatá verze proto páruje jinak. Oba seznamy identifikátorů si poznamenají pozice, seřadí se a projdou se vedle sebe jedním průchodem; dvojice se pak vypíšou v pořadí volání. Je to postup, který zná každý, kdo kdy sléval dva seřazené lístkové katalogy do jednoho. Podle autora vykreslí nová šablona bajt po bajtu totéž co stará – ověřoval to na 15 000 náhodně složených konverzacích s chybějícími, zdvojenými i přebývajícími identifikátory.
V souboru zůstala dvě makra, která už nikdo nevolá
Obě makra, kvůli kterým se blok procházel dokola, jsou v dnešní šabloně pořád definovaná, jen je už nic nevolá. Autor to v návrhu uvedl jako záměr: chtěl, aby se změna týkala jednoho bloku a nic dalšího.
Kdo GLM-5.3 provozuje a chce opravu mít, musí si stáhnout nový soubor chat_template.jinja; váhy se nemění. Pro běžný provoz je to rozdíl, který se nedá poznat – při desítkách volání v jednom tahu jde o setiny sekundy. Dává smysl u agentů, kteří spouštějí stovky nástrojů naráz, a u serveru, kde vykreslení šablony blokuje obsluhu ostatních dotazů. Tam, kde se na šablonu nehledí, se její obsah dostane do hry stejně – třeba když ji za vydavatele dopíše někdo cizí, jak se v září stalo u DeepSeeku.
Zdroje
- Návrh změny #31 u zai-org/GLM-5.3, Hugging Face – měření, rozprava s recenzentem, sloučeno 14. října 2026
- Návrh #36957 v SGLangu – popis vady z 29. srpna, odpověď Z.ai ze 4. září, zavřeno automatem 8. října
- Sloučený commit v repozitáři GLM-5.3