LLM Fundamentals
LLM je skratka pre large language model, teda veľký jazykový model. Je to program, ktorý prešiel obrovským množstvom textu a naučil sa v ňom štatistické zákonitosti — nie fakty ako fakty, ale to, čo po čom zvykne nasledovať. Jediná vec, ktorú v skutočnosti robí, je odhad ďalšieho kúska textu. Tento odhad opakuje dookola, kým mu nevyjde celá odpoveď.
Znie to podozrivo jednoducho na niečo, čo ti vie prepísať polovicu repozitára. Lenže všetko ostatné, čo poznáš pod menom chat, pamäť, nástroje či agenti, je len vrstva postavená okolo tejto jednej operácie. Preto sa oplatí vedieť, ako tá vrstva vyzerá zvnútra — keď rozumieš jej hraniciam, prestaneš sa čudovať, prečo raz odpovie skvele a inokedy vedľa.
Správy, system prompt a reasoning
Keď sa rozprávaš s modelom, nevzniká medzi vami žiadne spojenie, ktoré by si niečo pamätalo. Existuje len zoznam správ. Tie tvoje sa volajú user messages, tie od modelu assistant messages, a pri každom ďalšom kole posielaš celú históriu odznova. Model si nepamätá nič, len zakaždým dostane kompletný prepis toho, čo ste si doteraz povedali.
Ak chceš jeho správanie nejako usmerniť, slúži na to system prompt. Je to správa na úplnom začiatku histórie, ktorú model vidí, ale používateľ zvyčajne nie. A má prekvapivo veľkú váhu: keď si system prompt a používateľ protirečia, model sa spravidla drží systémového. Napíš doňho, že má odpovedať v Morseovke, a bude odpovedať v Morseovke aj vtedy, keď ho používateľ prosí, nech s tým prestane.
Kam v tomto zapadá reasoning? Nikam zvláštne. Keď model premýšľa nahlas, kým odpovie, tie úvahy sú len ďalšou časťou tej istej assistant správy. Práve v tom je celý trik, ktorý sa oplatí pochopiť: jedna správa sa skladá z viacerých častí.
Rovnaká mechanika drží aj súbory. PDF pošleš dnu ako časť správy a vygenerovaný obrázok príde von presne tým istým spôsobom.
A napokon tool cally. Predstav si, že modelu oznámiš, že má k dispozícii writeFile. Používateľ napíše „vytvor todo.md“ a model odpovie tool callom, ktorý má svoje id a parametre. Ty ho vykonáš u seba a pošleš späť tool result s tým istým id.
Presne takto, a nijak inak, sa Claude Code či Cursor dostanú k súborom na tvojom disku.
What messages you send to the LLM actually look like
short
The hidden security risk in your system prompts
Tokeny
Model v skutočnosti nikdy nevidí text. Vidí čísla, a tie čísla sa volajú tokeny. Prevod jedného na druhé má na starosti tokenizer a hovorí sa mu encoding: text sa rozseká na kúsky, ktoré tokenizer pozná, a každý kúsok dostane svoje číslo.
Decoding je tá istá cesta naopak. Čísla sa premenia späť na kúsky textu a tie sa pospájajú do výslednej vety.
Celý kolobeh teda vyzerá takto: tokenizer zakóduje tvoj vstup, model spracuje tokeny, vyprodukuje výstupné tokeny a tie sa nakoniec dekódujú späť na čitateľný text.
Za tokeny aj platíš, takže sa hodí vedieť, čo všetko sa do nich počíta. Do input tokenov ide celá história konverzácie, system prompt a aj definície všetkých tools, čo býva položka, na ktorú sa ľahko zabudne. Output tokeny sú to, čo model odpovie. Účtuje sa oboje, každé inou sadzbou, pričom output je typicky citeľne drahší. Najlacnejšia optimalizácia je preto navrhnúť prompt tak, aby model nemusel veľa písať.
Ako slovník vzniká
Tokenizer sa trénuje na veľkom korpuse textu, podobnom tomu, na akom sa trénuje samotný model. Skúsme si to na hračkárskom príklade s jedinou vetou: „the cat sat on the mat“. Najprv sa z nej vytiahnu všetky jednotlivé znaky a každý z nich sa stane vlastným tokenom. Potom sa hľadajú časté dvojice: TH a HE (obe dvakrát v slove „the“), AT (v „cat“, „sat“ aj „mat“). Aj tie dostanú svoje tokeny. A nakoniec sa skladajú skupiny zo skupín, takže z TH a HE vznikne THE ako jeden token pre celé slovo.
Cieľom je dostať sa k čo najväčšiemu slovníku, pretože čím je väčší, tým menej tokenov treba na to isté slovo. Slovo „understanding“ sa pri slovníku s tisíckou tokenov rozpadne na päť kusov, pri päťdesiattisíc na tri a pri dvestotisíc už len na dva.
Odtiaľ pramení aj slabina tokenizera: na nezvyčajných slovách sa zasekáva. Pekne to vidno na „O Frabjous Day“ z Carrollovej básne, kde pätnásť znakov spotrebuje sedem tokenov. „Frabjous“ je totiž vymyslené slovo, ktoré sa v korpuse prakticky nevyskytuje, takže preň neexistuje žiadna úspornejšia skratka.
Ak si to chceš osahať na vlastných textoch, pusti si tiktokenizer. Je to asi najrýchlejší spôsob, ako získať cit pre to, čo je drahé a čo nie.
Context window
Context window je všetko, čo má model v danom momente pred očami: system prompt, celá doterajšia história aj to, čo práve píše. Inými slovami input a output tokeny dokopy.
Keďže každé ďalšie kolo so sebou nesie všetky predošlé, počet tokenov s dĺžkou konverzácie neúprosne rastie.
A donekonečna to ísť nemôže. Každý model má natvrdo daný strop a keď ho prekročíš, API ti jednoducho vráti chybu.
Nepríjemnejšie je, že naraziť sa dá aj uprostred generovania. Správa sa začne písať pekne v limite a miesto jej dôjde niekde v polovici, pretože model si vlastný strop nestráži a dopredu si ho nevie rozpočítať.
Lost in the middle
Tvrdý strop je však ten menší z problémov. V dlhej histórii má na výsledok najväčší vplyv začiatok a koniec, kým tomu, čo leží v strede, venuje model citeľne menej pozornosti. A čo je horšie, čím väčšie okno, tým je tento efekt výraznejší.
Veľký context window nie je pozvánka ho zaplniť. Model s obrovským oknom trpí na lost-in-the-middle rovnako a občas nedokáže vytiahnuť ani informáciu, ktorú má priamo pred sebou. Preto pri hodnotení modelu neber veľkosť okna ako výhru: menej tokenov v kontexte dá lepší výsledok bez ohľadu na to, koľko ich model teoreticky unesie.
Tools
Tools sa modelu odovzdávajú cez system prompt a nie je v tom nič zázračné. Ich definície sa doslova vpíšu do systémovej správy a tvoj vlastný text sa zaradí pod ne.
Ku každému toolu pritom uvádzaš tri veci:
- názov, napríklad
writeFile; - popis, teda „Write a file to the file system“;
- parametre a ich typy, povedzme
pathacontent. Zapisujú sa v JSON Scheme, takže pokojne aj objekty, polia a iné zložitejšie štruktúry.
Zaujímavé začne byť to, čo príde potom. Používateľ napíše „vytvor súbor .gitignore“ a model si sám vyberie, ktorý tool na to použije. Nikde mu nemusíš prikázať „zavolaj tento tool“, to rozhodnutie robí on.
Tool call ešte nie je vykonanie. Model len vyprodukoval správu, a tým jeho práca končí. Kým to nespustíš ty na svojom stroji, nestalo sa vôbec nič.
To zároveň znamená, že ku každému toolu, ktorý si v system prompte deklaroval, musíš mať v kóde zodpovedajúcu funkciu. Keď dobehne, pošleš späť tool result s tým istým id, aké mal pôvodný tool call.
A jedna vec, na ktorej záleží viac, než sa zdá: posielaj späť aj chyby. Tool result môže byť úspech aj zlyhanie, a ak zlyhanie pred modelom zatajíš, nemá sa ako dozvedieť, že má skúsiť niečo iné.
Celý kolobeh teda ide takto:
Do system promptu vložíš definície tools v podobe JSON Schemy.
Používateľ pošle správu „vytvor súbor
.gitignore“.Model si vyberie tool a vráti tool call so správnymi parametrami.
Ty ten tool call zachytíš a vykonáš u seba na stroji.
Pošleš späť tool result s tým, ako to dopadlo.
Model vidí celú históriu aj s výsledkom a odpovie zhrnutím.
Nič viac za tým nie je. Tools sú spôsob, ako z modelu dostať správu určitého tvaru, zachytiť ju a vykonať, a na tejto jednoduchej slučke stojí každý coding agent, ktorý dnes používaš.
Agent vs workflow
Odkedy Anthropic vydal článok Building effective agents, hovorí sa o agentoch aj workflowoch prakticky všade. Oboje sú spôsoby, ako z modelu poskladať niečo výkonnejšie, a oboje orchestrujú viacero volaní. Ak robíš jediné volanie, nie je to ani jedno z toho.
Workflow
Workflow ide po vopred daných krokoch, ktoré si ako vývojár napísal do kódu. Jedno volanie ide do druhého, druhé do tretieho, a kód rozhoduje, čo príde ďalej aj kedy sa má celé zastaviť.
Agent
Agent žiadne vopred dané kroky nemá. Dostane sadu tools, teda zoznam možností, čo môže urobiť ďalej, a sám si vyberá, reaguje na výsledky a pokračuje. Skončí vtedy, keď on usúdi, že je hotovo. Je to model, ktorý si to vymýšľa za pochodu, čo mu dáva oveľa väčšiu moc, ale zároveň to robí menej predvídateľným.
Keď to zhrnieme, celý rozdiel visí na jednej otázke: kto rozhoduje, kedy sa to zastaví.
agent
Vhodný tam, kde kroky vopred nepoznáš a treba sa cez zložitý problém nejako preimprovizovať.
workflow
Vhodný tam, kde sa to isté robí znova a znova. Pri jasne zadanej úlohe dá workflow spravidla lepší výsledok než agent — len sa mu krivdí, lebo neznie tak vzrušujúco.
Pekne to vidno na paralelizácii. Vezmeš kus textu, rozdelíš ho na dve časti, každú necháš zhrnúť zvlášť a naraz, a nakoniec zhrnieš tie dve zhrnutia dokopy. Nič, čo by potrebovalo agenta.
Resources
- aihero.dev/llm-fundamentals — pôvodný kurz od Matta Pococka (AI Hero) aj s videami. Táto stránka je jeho prepis, diagramy sú z neho.
- Building effective agents — článok od Anthropicu, z ktorého celé delenie agent/workflow vychádza.
- tiktokenizer — playground, kde vidíš, na aké tokeny sa text rozpadne.