Pitanja za LLM and Generative AI Engineer intervju
15 često postavljanih pitanja za LLM and Generative AI intervju. Pitanja pokrivaju različite nivoe, a odgovore možete vežbati naglas u našem treneru za intervjue.
1Objasnite tokenizaciju na nivou podreči (subword tokenization) i zašto ima prednost u odnosu na tokenizaciju na nivou reči ili karaktera u savremenim jezičkim modelima.
Tokenizacija na nivou podreči je hibridni pristup segmentaciji teksta koji deli tekst na morfološke celine promenljive dužine ili podnizove zasnovane na frekvenciji pojavljivanja (kao što su 'un', 'break', 'able') umesto na cele reči ili pojedinačne karaktere. Algoritmi kao što su BPE (Byte-Pair Encoding), WordPiece i Unigram LM uče rečnik fiksne veličine iz korpusa za treniranje, pri čemu česte reči ostaju netaknute kao pojedinačni tokeni, dok se retke ili neviđene reči razlažu na poznate jedinice podreči. Tokenizacija na nivou podreči ima prednost u savremenim jezičkim modelima jer uspostavlja ravnotežu između veličine rečnika, dužine sekvence i otpornosti na reči van rečnika (OOV - Out-Of-Vocabulary). Čista tokenizacija na nivou reči zahteva preterano veliki rečnik (što dovodi do ogromnih matrica ugnježđavanja) i i dalje pati od OOV tokena koji se mapiraju u generičke `[UNK]` tokene. Nasuprot tome, čista tokenizacija na nivou karaktera eliminiše OOV probleme, ali generiše veoma dugačke sekvence koje drastično povećavaju računarsku složenost u mehanizmima pažnje (koji skaliraju kvadratno sa dužinom sekvence) i razređuju semantičku gustinu po tokenu. Tokenizacija na nivou podreči postiže optimalan kompromis održavajući dužine sekvenci upravljivim, veličine rečnika praktičnim (obično od 32k do 128k tokena), a stopu OOV reči na nuli (posebno kada se kombinuje sa rezervnim nivoom na bazi bajtova).
2Objasnite razliku između statičkih ugrađivanja reči (static word embeddings), kontekstualnih ugrađivanja (contextual embeddings) i skrivenih stanja transformatora (transformer hidden states).
Statička ugrađivanja reči, kontekstualna ugrađivanja i skrivena stanja transformatora predstavljaju progresivnu evoluciju u načinu na koji tekstualne reprezentacije beleže značenje i sintaksički kontekst.
1. Statička ugrađivanja reči (npr. Word2Vec, GloVe, FastText) dodeljuju jedan, fiksni vektor svakom tokenu iz rečnika bez obzira na kontekst rečenice. U ovoj paradigmi, višeznačne reči poput „banka” (rečna obala naspram finansijske institucije) ili „apple” (voće naspram tehnološke kompanije) imaju identične vektorske reprezentacije u svim kontekstima, oslanjajući se na statičku tabelu pretrage.
2. Kontekstualna ugrađivanja (npr. rani ELMo, BERT reprezentacije tokena ili ugrađivanja rečenica iz Bi-Encoder modela) proizvode reprezentacije gde je vektor za određeni token dinamička funkcija njegovog okružujućeg konteksta. U modelima BERT ili ELMo, „bank” u izrazu „river bank” dobija potpuno drugačiji vektor ugrađivanja u poređenju sa „bank” u izrazu „deposit money at the bank”.
3. Skrivena stanja transformatora odnose se na međuvektorske reprezentacije proizvedene na svakom pojedinačnom sloju transformatorske mreže tokom prolaza unapred (forward pass). Polazeći od ulaznih ugrađivanja tokena na sloju 0, svaki uzastopni sloj transformatora primenjuje mehanizam samopažnje (self-attention) i transformacije unapred (feed-forward), generišući sekvencu vektora skrivenih stanja h_l na sloju l. Dok skrivena stanja poslednjeg sloja funkcionišu kao kontekstualna ugrađivanja visokog nivoa, niža i srednja skrivena stanja beleže sintaksičke, leksičke i strukturne karakteristike nižeg nivoa. Prema tome, skrivena stanja transformatora obuhvataju ceo vertikalni kontinuum reprezentacija sloj po sloj kroz čitavu mrežu.
import torch
from transformers import AutoTokenizer, AutoModel
tokenizer = AutoTokenizer.from_pretrained('bert-base-uncased')
model = AutoModel.from_pretrained('bert-base-uncased', output_hidden_states=True)
text1 = 'River bank'
text2 = 'Bank deposit'
inputs1 = tokenizer(text1, return_tensors='pt')
inputs2 = tokenizer(text2, return_tensors='pt')
with torch.no_grad():
out1 = model(**inputs1)
out2 = model(**inputs2)
# Layer 0 (Input token embeddings - static lookup before self-attention)
static_bank_1 = out1.hidden_states[0][0, 2] # 'bank'
# Layer 12 (Final contextual hidden state after all attention layers)
contextual_bank_1 = out1.hidden_states[12][0, 2]
contextual_bank_2 = out2.hidden_states[12][0, 1]
print('Cosine similarity of bank in different contexts (Layer 12):',
torch.cosine_similarity(contextual_bank_1, contextual_bank_2, dim=0).item())
3Objasnite šta predstavlja prostor ugrađivanja (embedding space) i kako se interpretira kosinusna sličnost za tekstualne vektorske reprezentacije (embeddings).
Prostor ugrađivanja je neprekidan, visokodimenzionalni vektorski prostor R^d u koji se preslikavaju diskretni tekstualni entiteti (reči, rečenice ili dokumenti) tako da semantičke, sintaksičke ili relacione sličnosti odgovaraju geometrijskoj blizini i usmerenju. U ovom prostoru, rastojanja i uglovi odražavaju semantičku povezanost.
Kosinusna sličnost meri kosinus ugla theta između dva vektora u i v, i računa se kao:
Kosinusna sličnost(u, v) = (u . v) / (||u|| ||v||)
Kosinusna sličnost se kod tekstualnih vektorskih reprezentacija interpretira na sledeći način:
- Raspon i usmerenje: Daje skalarnu vrednost tipično ograničenu u opsegu [-1, 1] (ili [0, 1] za nenegativne vektore). Vrednost bliska 1.0 ukazuje na to da dva vektora pokazuju u praktično istom smeru, što odražava visoku semantičku sličnost ili tematsko poklapanje. Vrednost blizu 0.0 implicira ortogonalnost (semantičku nezavisnost ili nepovezanost), dok negativne vrednosti ukazuju na suprotna usmerenja.
- Invarijantnost u odnosu na magnitudu: Za razliku od Euklidskog rastojanja (L2 rastojanje) ili skalarnog proizvoda, kosinusna sličnost normalizuje dužinu vektora. Kod tekstualnih reprezentacija, magnituda vektora ponekad može korelirati sa dužinom sekvence, učestalošću tokena ili specifičnošću termina. Fokusiranjem isključivo na usmerenje, kosinusna sličnost izoluje semantički pravac od razlika u veličini vektora.
4Objasnite razliku između ugrađivanja tokena (token embeddings), pozicionih ugrađivanja (positional embeddings) i ugrađivanja segmenata ili tipova (segment or type embeddings) u ulazima transformerskih modela.
U ulazima transformerskih modela (posebno kod arhitektura u BERT stilu), ulazna reprezentacija za svaki token se obično formira sabiranjem po elementima tri različita vektora ugrađivanja (embeddings): 1. Ugrađivanja tokena (Token Embeddings): Mapiraju diskretne identifikatore tokena iz rečnika u guste vektore koji predstavljaju osnovni semantički i leksički identitet tokena. 2. Poziciona ugrađivanja (Positional Embeddings): Unose informacije o redosledu tokena i sekvencijalnom indeksu u reprezentaciju, kompenzujući činjenicu da je mehanizam samopažnje (self-attention) inherentno invarijantan na permutacije. 3. Ugrađivanja segmenata ili tipova tokena (Segment or Token Type Embeddings): Razlikuju različite tekstualne raspone ili rečenice spakovane u jednu ulaznu sekvencu (kao što su rečenica A i rečenica B u zadacima uparene klasifikacije ili odgovaranja na pitanja). Kombinovanje ovih ugrađivanja obezbeđuje jedinstveni gusti ulazni tenzor koji kodira značenje tokena, poziciju i grupisanje sekvenci pre prosleđivanja u prvi sloj transformera.
import torch
import torch.nn as nn
vocab_size, max_seq_len, num_segments, d_model = 30522, 512, 2, 768
tok_embed = nn.Embedding(vocab_size, d_model)
pos_embed = nn.Embedding(max_seq_len, d_model)
seg_embed = nn.Embedding(num_segments, d_model)
input_ids = torch.tensor([[101, 7592, 102, 2023, 102]]) # Token IDs
type_ids = torch.tensor([[0, 0, 0, 1, 1 ]]) # Segment IDs (Sentence A vs B)
positions = torch.arange(input_ids.size(1)).unsqueeze(0) # Indices: [0, 1, 2, 3, 4]
# Final representation is the element-wise sum
input_rep = tok_embed(input_ids) + pos_embed(positions) + seg_embed(type_ids)
print(input_rep.shape)
5Objasnite mehanizam pažnje (engl. attention) za povezivanje tokena u sekvenci, uključujući upite (queries), ključeve (keys), vrednosti (values) i višeglavu pažnju (multi-head attention).
Pažnja (attention) je mehanizam koji omogućava tokenima u sekvenci da dinamički usmeravaju informacije i odmeravaju relevantnost svih ostalih tokena na osnovu kontekstualnog poklapanja. Linearne projekcije transformišu ulaz svakog tokena u tri vektora:
- Upit (Query - Q): Predstavlja informaciju koju trenutni token traži.
- Ključ (Key - K): Predstavlja atribute ili sadržaj koji token nudi za poređenje sa upitima.
- Vrednost (Value - V): Sadrži stvarne podatke koji se agregiraju.
Kod skalirane pažnje skalarnog proizvoda (scaled dot-product attention), rezultati pažnje računaju se množenjem upita i ključeva ($Q K^T$), skaliraju faktorom $\frac{1}{\sqrt{d_k}}$ kako bi se sprečio problem nestajanja gradijenta pri velikim dimenzijama, i normalizuju pomoću softmax funkcije. Konačni izlaz predstavlja ponderisanu sumu vrednosti:
$$\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V$$
Višeglava pažnja (Multi-Head Attention - MHA) projektuje $Q$, $K$ i $V$ u više nezavisnih reprezentacionih potprostora (glava) paralelno. To omogućava modelu da istovremeno obraća pažnju na različite tipove relacija (npr. sintaksičku strukturu, koreferencu, zavisnosti na velikim rastojanjima) kroz različite pozicije. Izlazi svih glava se nadovezuju (konkateniraju) i linearno projektuju nazad na početnu dimenziju modela.
6Objasnite kako se maskiranje mehanizma pažnje razlikuje kod kauzalnih dekodera u odnosu na dvosmerne enkodere i koja ponašanja omogućava ili sprečava.
Maskiranje mehanizma pažnje (attention masking) kontroliše kojim tokenima je dozvoljeno da obraćaju pažnju na druge tokene tako što postavlja logite pažnje (rezultate pre softmax funkcije) na $-\infty$ za nedozvoljene parove, osiguravajući da njihova težina pažnje nakon primene softmax funkcije bude striktno 0.
1. Kauzalni dekoderi (npr. GPT, LLaMA): Koriste donju trougaonu kauzalnu (autoregresivnu) masku. Token na poziciji $i$ može obraćati pažnju samo na pozicije $j \le i$. Ovo sprečava pažnju ka budućim tokenima, omogućavajući autoregresivno generisanje token po token tokom faze inferencije i sprečavajući curenje informacija o budućim tokenima (label leakage) tokom paralelizovanog treniranja.
2. Dvosmerni enkoderi (npr. BERT): Ne koriste kauzalnu masku; svaki token može obraćati pažnju na sve prethodne i buduće tokene duž sekvence. Oni koriste maske za dopunjavanje (padding masks) kako bi sprečili validne tokene da obraćaju pažnju na prazne `[PAD]` tokene u sekvencama unutar batch-a. Dvosmerna pažnja proizvodi bogate svestrane kontekstualne reprezentacije idealne za zadatke razumevanja, ali sprečava direktno autoregresivno generisanje teksta u jednom prolazu.
import torch
import torch.nn.functional as F
scores = torch.randn(3, 3)
# Create upper-triangular mask for future positions
causal_mask = torch.triu(torch.ones(3, 3, dtype=torch.bool), diagonal=1)
# Mask future positions with -inf before softmax
masked_scores = scores.masked_fill(causal_mask, float('-inf'))
atten_weights = F.softmax(masked_scores, dim=-1)
print(atten_weights)
7Objasnite razliku između arhitektura transformera koje koriste samo enkoder (encoder-only), samo dekoder (decoder-only) i kombinaciju enkoder-dekoder (encoder-decoder) za jezičke zadatke.
Tri osnovne arhitekture transformera se suštinski razlikuju po šablonima maskiranja pažnje i ciljnim operativnim zadacima:
1. Samo enkoder (Encoder-Only, npr. BERT, RoBERTa): Koristi dvosmernu samopažnju (bidirectional self-attention) gde svaki token može istovremeno da obrati pažnju na sve ostale tokene u sekvenci. Generiše bogate kontekstualne reprezentacije za celokupnu ulaznu sekvencu, što ga čini idealnim za klasifikaciju, ekstraktivno odgovaranje na pitanja (QA - Question Answering) i reprezentaciju obeležja. Prirodno ne može da generiše autoregresivni tekst.
2. Samo dekoder (Decoder-Only, npr. GPT-3, Llama, Mistral): Koristi uzročnu (jednosmernu) samopažnju (causal self-attention), gde token $i$ može da obraća pažnju samo na tokene na pozicijama $j \le i$. Trenira se autoregresivno predviđanjem sledećeg tokena i služi kao standardna arhitektura za generativne jezičke modele, generisanje koda i razgovore otvorenog tipa.
3. Enkoder-dekoder (Encoder-Decoder, npr. T5, BART): Kombinuje dvosmerni enkoder sa autoregresivnim uzročnim dekoderom. Pored uzročne samopažnje nad generisanim tokenima, dekoder koristi slojeve unakrsne pažnje (cross-attention) koji ispituju izlazne reprezentacije enkodera. Ova arhitektura je namensko rešenje za zadatke transformacije sekvence u sekvencu (sequence-to-sequence), kao što su prevođenje i sažimanje teksta.
8Objasnite kako izbor tokenizatora na nivou bajtova, onih koji prepoznaju Unicode i višejezičnih tokenizatora utiče na kvalitet modela, cenu i pravičnost među jezicima.
Odluke o dizajnu tokenizatora — kao što su segmentacije na nivou bajtova naspram onih svesnih Unicode standarda, kao i raspodela višejezičnog rečnika — direktno utiču na kvalitet krajnjeg modela, troškove inferencije/treniranja i jezičku pravičnost. U pogledu troškova i pravičnosti, tokenizatori trenirani pretežno na korpusima engleskog jezika ili tekstovima na latinici dodeljuju većinu unosa u rečniku engleskim rečima i morfemama. Zbog toga engleski postiže visoku kompresiju (npr. ~1,3 tokena po reči), dok se nelatinična pisma (npr. arapski, devanagari, tajlandski, kineski) ili jezici sa malo resursa često fragmentišu na višestruke podreči ili sirove UTF-8 bajtove (često 3 do 6 tokena po reči). Ova nejednakost se često naziva „porez na tokene“ (token tax) ili „disbalans stope plodnosti tokena“ (fertility rate imbalance): korisnici koji ne pišu na engleskom plaćaju znatno više po jedinici semantičkog sadržaja pri naplati API-ja (Application Programming Interface), znatno brže troše kontekstualni prozor i imaju veće kašnjenje (latenciju). U pogledu kvaliteta, tokenizatori na nivou bajtova (poput Byte-level BPE u GPT-2/GPT-4 ili SentencePiece sa rezervnom bajt opcijom u LLaMA) u potpunosti izbegavaju rušenja izazvana neviđenim karakterima i greške nepoznatih reči (UNK) jer se svaki važeći UTF-8 niz razlaže na bajt tokene. Međutim, prekomerna fragmentacija bajtova narušava kvalitet reprezentacije jer transformator mora da utroši slojeve rekombinujući fragmente bajtova u semantičke koncepte pre izvođenja zaključivanja na visokom nivou. Povećanje veličine višejezičnog rečnika (npr. proširenje sa 32k na 128k+ tokena) uravnotežuje stopu fragmentacije i poboljšava performanse na zadacima širom različitih jezika, po ceni umereno većeg ulazno/izlaznog sloja za ugrađivanje (embedding layer).
9Koji artefakti tokenizacije se javljaju pri numeričkom rezonovanju, generisanju koda ili retkom Unicode tekstu i kako ih specijalizovani tokenizatori mogu ublažiti?
Artefakti tokenizacije nastaju kada tokenizatori podreči nekonzistentno dele strukturirani, numerički ili retki tekst, sprečavajući model da prepozna osnovnu semantičku ili sintaksnu pravilnost. Ključni artefakti uključuju:
1. Artefakti pri numeričkom rezonovanju: Standardni BPE (Byte Pair Encoding) tokenizatori obučeni na opštem tekstu dele brojeve na proizvoljne dužine isečaka na osnovu frekvencije (npr. '12345' se može tokenizovati kao ['12', '345'], dok se '12346' tokenizuje kao ['123', '46']). Ovo nekonzistentno grupisanje narušava poravnanje težinskih mesta cifara (jedinice, desetice, stotine) i otežava aritmetičko rezonovanje.
2. Artefakti pri generisanju koda: Uvlačenje koda (početni razmaci/tabulatori) i višečlani operatori (npr. '==', '!=', '->') se često nepravilno dele preko granica razmaka i znakova, što dovodi do grešaka u uvlačenju, prekomernog broja tokena u duboko uvučenom kodu i sintaksnih oštećenja.
3. Artefakti kod retkih Unicode i Emoji karaktera: Višebajtne UTF-8 sekvence (poput složenih emodžija sa spajačima nulte širine ili retkih pisama) dele se na sirove bajt-tokene koji nemaju pojedinačno semantičko značenje, što dovodi do haluciniranih karaktera ili oštećenog prikazivanja glifova pri generisanju.
Specijalizovani tokenizatori smanjuju ove artefakte korišćenjem prilagođenih pravila pre-tokenizacije i ograničenja rečnika:
- Razdvajanje cifara: Primoravanje na tokenizaciju pojedinačnih cifara (npr. regularni izraz koji deli svaku cifru `0-9` u zaseban token) obezbeđuje uniformno predstavljanje pozicionih vrednosti za matematičko rezonovanje.
- Namenski tokeni za beline/uvlačenje: Dodavanje eksplicitnih tokena za uvlačenja sa više razmaka (npr. 2, 4, 8 razmaka) i očuvanje ključnih reči i operatora programskih jezika.
- Regex pre-tokenizacija / rezervne varijante na nivou bajtova: Korišćenje regex razdvajača (poput GPT-4/tiktoken regularnih izraza) koji odvajaju interpunkciju, slova i brojeve u stroge kategorije pre izračunavanja BPE spajanja, čime se sprečava spajanje različitih kategorija (npr. sprečava se da se 'a=10' spoji u jedan token).
import tiktoken
# tiktoken cl100k_base (GPT-4 / ChatGPT) enforces digit and whitespace handling
enc = tiktoken.get_encoding('cl100k_base')
num1 = '12345'
num2 = '12346'
code_indent = ' def foo():'
print('Tokens num1:', [enc.decode([t]) for t in enc.encode(num1)])
print('Tokens num2:', [enc.decode([t]) for t in enc.encode(num2)])
print('Tokens code:', [enc.decode([t]) for t in enc.encode(code_indent)])
10Analizirajte kompromise mehanizma pažnje sa dugačkim kontekstom (long-context attention), uključujući kvadratnu punu pažnju, pažnju sa kliznim prozorom (sliding-window attention), retku ili globalnu pažnju, memorijski trošak KV (Key-Value) keša i razvodnjavanje pažnje (attention dilution).
Skaliranje mehanizma pažnje na dugačke kontekstualne prozore donosi kompromise u pogledu računanja, zauzeća memorije i vernosti modela:
1. Kvadratna puna pažnja naspram pažnje sa kliznim prozorom / retke pažnje: Standardna puna pažnja skalira se kvadratno ($O(N^2)$) u proračunu i memoriji za aktivacije sa dužinom sekvence $N$. Pažnja sa kliznim prozorom (lokalna pažnja) ograničava pažnju na fiksno susedstvo $W$, smanjujući složenost na $O(N \cdot W)$, ali zahteva više slojeva za propagiranje informacija između udaljenih tokena. Obrasci retke ili globalne pažnje kombinuju lokalne prozore sa odabranim globalnim sidrišnim tokenima kako bi zadržali skaliranje od $O(N)$ uz omogućavanje komunikacije na velikim udaljenostima.
2. Memorijski trošak KV keša: Tokom autoregresivnog generisanja, ključevi i vrednosti (KV) za sve prethodne tokene se keširaju kako bi se izbeglo suvišno računanje. Memorija za KV keš skalira se linearno sa dužinom sekvence ($O(B \cdot L \cdot H_{KV} \cdot D \cdot N)$). Za veoma dugačke kontekste (32k–128k+ tokena), KV keš troši desetine gigabajta GPU VRAM-a po paketu (batch), stvarajući usko grlo za maksimalnu veličinu paketa i memorijski protok.
3. Razvodnjavanje pažnje (Lost-in-the-Middle): Kako kontekst raste, imenilac softmax funkcije sumira desetine hiljada tokena, raspoređujući masu verovatnoće tanko preko irelevantnog konteksta. Ovo povećanje entropije razvodnjava oštrinu pažnje, degradirajući sposobnost modela da pouzdano pronađe i vrati specifične informacije ugnježdene u sredini dugačkih upita (prompts).
11Uporedite MHA (Multi-Head Attention), MQA (Multi-Query Attention) i GQA (Grouped-Query Attention) i objasnite kako utiču na memoriju za KV (Key-Value) keš i propusnost dekodovanja.
Multi-Head Attention (MHA), Multi-Query Attention (MQA) i Grouped-Query Attention (GQA) se razlikuju po tome kako se Key ($K$) i Value ($V$) glave dele između Query ($Q$) glava:
1. Multi-Head Attention (MHA): Ima jednak broj $Q$, $K$ i $V$ glava ($H_Q = H_{KV}$, odnos 1:1). Svaka query glava obrađuje sopstvene nezavisne reprezentacije ključeva i vrednosti. Iako pruža veliku izražajnost, zahteva keširanje zasebnih KV matrica za svaku glavu.
2. Multi-Query Attention (MQA): Koristi više $Q$ glava ($H$), ali samo jednu deljenu $K$ glavu i jednu deljenu $V$ glavu (odnos $H:1$). Ovo smanjuje veličinu KV keša za faktor $H$, ali može dovesti do blagog pada kvaliteta ili nestabilnosti pri treniranju modela.
3. Grouped-Query Attention (GQA): Grupiše $Q$ glave u $G$ particija, gde svaka grupa deli jednu zajedničku $K$ i $V$ glavu (npr. 8 $Q$ glava po jednoj KV glavi). GQA nudi optimalan kompromis, zadržavajući praktično sav kvalitet modelovanja koji pruža MHA, uz očuvanje memorijskih prednosti koje nudi MQA.
Uticaj na KV keš i propusnost dekodovanja:
Autoregresivno generisanje tokena (dekodovanje) je ograničeno memorijskim protokom (memory-bandwidth bound) jer GPU mora da prenese ceo KV keš iz HBM (High-Bandwidth Memory) memorije u SRAM na čipu za svaki pojedinačni generisani token. Smanjenjem broja KV glava za faktor $H/G$ (npr. $4\times$ do $8\times$ u GQA, ili $32\times+$ u MQA):
- Memorijski otisak KV keša se proporcionalno smanjuje, što omogućava znatno veće veličine batch-a pri opsluživanju u GPU VRAM memoriji.
- Količina podataka koja se čita iz HBM memorije po tokenu drastično opada, što znatno povećava propusnost dekodovanja tokena.
# Model with 32 Query Heads
num_q_heads = 32
mha_kv_heads = 32 # 1:1 ratio
gqa_kv_heads = 8 # 4:1 ratio (4 query heads per KV head)
mqa_kv_heads = 1 # 32:1 ratio (1 shared KV head)
print(f"KV Cache Size Relative to MHA:")
print(f"MHA: {mha_kv_heads / mha_kv_heads * 100:.1f}%")
print(f"GQA: {gqa_kv_heads / mha_kv_heads * 100:.1f}%")
print(f"MQA: {mqa_kv_heads / mha_kv_heads * 100:.1f}%")
12Objasnite kako FlashAttention ubrzava računanje egzaktne pažnje bez promene izlaza mehanizma pažnje.
FlashAttention ubrzava računanje mehanizma pažnje tako što čini algoritam svesnim ulazno-izlaznih operacija (IO-aware) — minimizujući prenos podataka čitanja i upisa između spore GPU HBM (High Bandwidth Memory) memorije i brze SRAM memorije na samom čipu, umesto da pokušava da smanji ukupan broj aritmetičkih operacija sa pokretnim zarezom (FLOP - Floating Point Operations).
Standardni mehanizam pažnje materijalizuje međumatrice rezultata i verovatnoća pažnje dimenzija $N \times N$ u HBM memoriji, što stvara glavno usko grlo u propusnom opsegu memorije. FlashAttention to rešava pomoću tri ključna mehanizma:
1. **Popločavanje (Tiling):** Deli Query, Key i Value matrice na blokove koji u potpunosti staju u brzu SRAM memoriju na GPU čipu.
2. **Online Softmax:** Izračunava softmax inkrementalno po blokovima prateći tekuće maksimume i sume za normalizaciju, ažurirajući delimične izlaze bez potrebe za čuvanjem celokupne materijalizovane matrice dimenzija $N \times N$ u memoriji.
3. **Egzaktno ponovno izračunavanje (Exact Recomputation):** Tokom prolaza unazad (backward pass), algoritam ne čita sačuvane međumatrice pažnje iz HBM memorije; umesto toga, on ih ponovo izračunava u hodu unutar SRAM memorije na osnovu sačuvanih tekućih statistika.
Pošto se ne koriste aproksimacije, faktorizacije niskog ranga niti heuristike odbacivanja tokena, izlaz je matematički egzaktan do nivoa numeričke preciznosti pokretnog zareza, dok se memorijski otisak u HBM memoriji smanjuje sa $O(N^2)$ na $O(N)$.
13Dizajnirajte determinističke agentske tokove posla koristeći planere, automate stanja, DAG (Directed Acyclic Graph) strukture, tipizirano međustanje, ograničen broj ponovnih pokušaja i verifikaciju rezultata alata umesto otvorenih agentskih petlji.
Otvorene agentske petlje (npr. neograničene autonomne ReAct petlje) u produkciji često pate od nedeterminističkog grananja, beskonačnih petlji, nekontrolisane potrošnje tokena i odstupanja stanja. Deterministički agentski tok posla zamenjuje petlje slobodne forme strukturisanim, preglednim tokom kontrole:
1. Automati stanja i DAG strukture: Tok kontrole se definiše kao eksplicitni usmereni aciklični graf ili konačni automat stanja (npr. LangGraph, Temporal, AWS Step Functions). Prelazi između čvorova zavise od eksplicitnih uslova i tipiziranih ishoda, a ne od proizvoljnih odluka modela.
2. Tipizirano međustanje: Stanje koje se deli između čvorova modeluje se strogim šemama (npr. Pydantic modeli ili dataclasses). Čvorovi vrše validirane operacije čitanja i pisanja, sprečavajući odstupanje šeme ili neispravno stanje.
3. Planeri: Strukturisani planeri unapred generišu ograničen plan (npr. uređenu listu koraka zasnovanu na enum tipovima) ili biraju iz ograničenog skupa validnih prelaza stanja, umesto da slobodno odlučuju o sledećim akcijama bez ograničenja.
4. Verifikacija rezultata alata: Izlazi koje alati vraćaju deterministički se validiraju u odnosu na šeme i poslovna pravila pre ažuriranja stanja ili prosleđivanja nizvodnim LLM koracima.
5. Ograničeni ponovni pokušaji i rezervni mehanizmi: Svaki korak primenjuje eksplicitne budžete ponovnih pokušaja, eksponencijalno odlaganje (exponential backoff), vremenska ograničenja (timeouts) i rezervne prelaze (npr. eskalacija na ljudsku proveru ili bezbedno odustajanje) kako bi se garantovao završetak izvršavanja.
from pydantic import BaseModel
from typing import Optional, Literal
class WorkflowState(BaseModel):
user_query: str
extracted_id: Optional[str] = None
verification_status: Literal["PENDING", "VERIFIED", "FAILED"] = "PENDING"
retry_count: int = 0
max_retries: int = 3
def execute_validation_node(state: WorkflowState) -> WorkflowState:
if state.retry_count >= state.max_retries:
state.verification_status = "FAILED"
return state
try:
result = call_verification_service(state.extracted_id)
state.verification_status = "VERIFIED" if result.is_valid else "FAILED"
except Exception:
state.retry_count += 1
return state
14Projektujte politiku pouzdanosti i uzdržavanja od odgovora za LLM (Large Language Model) asistenta koji odgovara na pitanja u regulisanim domenima.
U regulisanim domenima (kao što su zdravstvo, bankarstvo, pravo i usklađenost sa propisima), netačni odgovori nose regulatorne kazne, pravnu odgovornost i bezbednosne rizike. Robusna politika pouzdanosti i uzdržavanja od odgovora kombinuje višesignalno kalibrisano bodovanje pouzdanosti, stepenovane pragove odgovora i determinističke tokove eskalacije:
1. Višesignalna kalibracija pouzdanosti: Sirove verovatnoće tokena (logprobs) LLM-a često su loše kalibrisane na upitima van domena treninga. Ocena pouzdanosti treba da objedini više nezavisnih signala:
- Ocena utemeljenosti u preuzetim podacima (Retrieval Grounding Score): Semantička sličnost i pouzdanost ponovnog rangiranja (re-ranking) preuzetih segmenata dokaza.
- Logička posledica na nivou tvrdnje (NLI, Natural Language Inference): Modeli zaključivanja na prirodnom jeziku koji proveravaju da li je svaka izvučena tvrdnja logički podržana preuzetim kontekstom izvora.
- Semantička entropija / Samokonzistentnost: Merenje semantičke konzistentnosti kroz više generisanih uzoraka.
- Logprobs tokena modela: Minimalne i prosečne verovatnoće (logprobs) na ključnim imenovanim entitetima i činjeničnim tokenima.
2. Stepenovana politika uzdržavanja od odgovora:
- Visoka pouzdanost (ocena >= visoki prag): Direktno isporučite generisani odgovor sa navođenjem citata unutar teksta.
- Srednja pouzdanost / Dvosmisleno (niski prag <= ocena < visoki prag): Pružite konzervativan odgovor sa eksplicitnim ogradama, napomenama o odricanju odgovornosti ili zatražite od korisnika dodatna pojašnjenja.
- Niska pouzdanost / Van opsega (ocena < niski prag): Potpuno uzdržavanje od odgovora sa standardizovanom porukom o odbijanju.
3. Eskalacija i proverljivost usklađenosti:
- Deterministička eskalacija: Uzdržavanja od odgovora ili kritična neslaganja se automatski prosleđuju u redove za ljudski pregled (HITL, human-in-the-loop) ili sisteme tiketa za agente sa punim kontekstom.
- Revizorski trag i poreklo podataka (lineage): Kompletna telemetrija — uključujući heševe upita, identifikatore preuzetih dokumenata, ocene pojedinačnih komponenti pouzdanosti i konačne odluke o usmeravanju — mora se beležiti radi regulatorne revizije.
15Dizajnirajte strategiju usmeravanja modela koja bira između malih, srednjih i velikih modela na osnovu složenosti zahteva, cene, rizika i zahteva za kvalitetom.
Produkciona arhitektura za usmeravanje modela raspoređuje dolazne zahteve između malih (npr. SLM modeli od 1B–8B parametara), srednjih (npr. modeli od 14B–70B) i velikih slojeva (npr. najnapredniji frontier modeli ili veliki MoE modeli) balansirajući složenost, latenciju, rizik i troškove računanja. Tok usmeravanja uglavnom kombinuje statička pravila, prediktivno usmeravanje i dinamičke kaskade za preusmeravanje u slučaju neuspeha: 1. Deterministički/statički filteri pravila: Filtriraju zahteve prema nivou korisnika, strogim SLA ugovorima o nivou usluge za latenciju, regulatornom/domenskom riziku (npr. medicinska dijagnostika ili pravni nacrti se usmeravaju direktno na modele najvišeg nivoa) ili jednostavnim zadacima koji odgovaraju pravilima (npr. osnovni regex/formatiranje ka malim modelima). 2. Prediktivno usmeravanje na osnovu složenosti: Brz, lagan klasifikator (poput pretrage sličnosti ugrađivanja (embeddings), cross-encoder modela ili malog SLM usmerivača) ocenjuje složenost zahteva, dubinu rezonovanja i nejasnoću domena kako bi unapred odabrao najisplativiji nivo. 3. Dinamičko izvršavanje i kaskade eskalacije: Zahtev se prvo šalje manjem modelu i procenjuje se pouzdanost izlaza (kroz verovatnoće tokena logprobs/entropiju, validnost strukturisane šeme ili provere zaštitnih mehanizama). Ako je pouzdanost ispod praga ili validacija ne uspe, usmerivač eskalira na srednji ili veliki model. Ključni kompromisi sistema uključuju dodatno kašnjenje usmerivača u odnosu na uštedu u računanju, vremenske budžete za preusmeravanje tokom skokova u saobraćaju i kontinuiranu evaluaciju (npr. evaluaciju u senci radi praćenja promene kvaliteta izlaza kroz nivoe).
class DynamicModelRouter:
def __init__(self, small_client, medium_client, large_client, classifier, guardrail):
self.small = small_client
self.medium = medium_client
self.large = large_client
self.classifier = classifier
self.guardrail = guardrail
async def route_and_execute(self, request):
# 1. Deterministic Risk Gate
if request.risk_level == "high" or request.domain in ["legal", "medical_compliance"]:
return await self.large.generate(request.prompt)
# 2. Predictive Complexity Classifier
complexity = self.classifier.predict_complexity(request.prompt) # 0.0 to 1.0
if complexity < 0.35:
response = await self.small.generate(request.prompt)
if self.guardrail.is_acceptable(response):
return response
return await self.medium.generate(request.prompt) # Fallback
if complexity < 0.75:
response = await self.medium.generate(request.prompt)
if self.guardrail.is_acceptable(response):
return response
return await self.large.generate(request.prompt) # Fallback
# 3. High complexity frontier execution
return await self.large.generate(request.prompt)