Mundarija (22)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. API parametrlari: 24.9 dagi mexanizmlar
- 2.2. temperature, top_p va top_k birga
- 2.3. max_tokens, stop ketma-ketliklari va stop_reason
- 2.4. Chastota va mavjudlik jarimalari
- 2.5. Determinizm: temperature=0 nega har doim bir xil emas
- 2.6. Kesilgan javobni qayta ishlash
- 2.7. Vazifa turiga qarab parametr tanlash
- 2.8. Tuzoqlar
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — API uslubidagi parametrlar to'ri
- Misol 2 — Takror jarimalari va ularning yon ta'siri
- Misol 3 — Determinizm: float tartibi, batch va aniqlik
- Misol 4 — stop_reason: kesilgan javobni qayta ishlash
- 5. To'g'ri va noto'g'ri tushunishlar
- 6. Keng tarqalgan xatolar va yechimlari
- 7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 8. Eng yaxshi amaliyotlar
- 9. Amaliy topshiriq
- Xulosa
25.3-dars: Generatsiya parametrlari
25-QISM — KATTA TIL MODELLARI · 3-dars
1. Kirish va motivatsiya
24.9-darsda generatsiya strategiyalarini noldan yozgan edik: greedy, temperature, top-k, top-p. LLM API sida xuddi shu tugmalar so'rov parametrlari sifatida keladi — temperature, top_p, top_k, max_tokens, stop_sequences — va javob bilan birga stop_reason (javob nima uchun tugadi) hamda usage (nechta token sarflandi) qaytadi. Bu darsda o'sha mexanizmlarni takrorlamaymiz, balki ularga API foydalanuvchisi ko'zi bilan qaraymiz: qaysi parametr nimani o'zgartiradi, qaysi biri narxga ta'sir qiladi, qaysi biri javobni jimgina buzadi va nega temperature=0 ham ba'zan boshqa javob beradi.
Real vaziyat. Jamoa mahsulot tavsiflarini avtomatik yozuvchi xizmat qurdi. Ishlab chiqishda hammasi yaxshi edi; ishga tushgach uchta shikoyat keldi. Birinchisi: tavsiflarning bir qismi jumla o'rtasida uzilib qolgan — max_tokens kichik edi, kod esa stop_reason ni tekshirmasdan matnni saytga chiqargan. Ikkinchisi: takror so'zlarni kamaytirish uchun "chastota jarimasi" yoqildi — takror kamaydi, lekin tavsiflar sezilarli qisqardi, chunki jarima vergul va nuqtani ham "takror" deb jazoladi. Uchinchisi: sinov uchun temperature=0 qo'yilgan edi, lekin bir xil so'rov ikki marta turli javob qaytardi va regression testlar "tasodifan" yiqila boshladi. Bu darsning to'rt misoli aynan shu uch holatni kichik modelda o'lchaydi.
Bu darsda API uslubidagi yarat() funksiyasini o'zimiz o'rgatgan kichik modelga quramiz, parametrlar to'rini juftlashgan taqqoslash bilan o'lchaymiz, takror jarimalarining yon ta'sirini ko'rsatamiz, float yig'indi tartibi determinizmni qanday buzishini ko'ramiz va kesilgan javoblarni qayta ishlash strategiyalarini narx bilan solishtiramiz.
Bu darsda:
- API parametrlari: 24.9 dagi mexanizmlarning nomlari
- temperature, top_p, top_k — birga ishlatish
-
max_tokens, stop ketma-ketliklari vastop_reason - Chastota va mavjudlik jarimalari
- Determinizm:
temperature=0nega har doim bir xil emas - Kesilgan javobni qayta ishlash
- Vazifa turiga qarab parametr tanlash
- Tuzoqlar
ℹ Misollar real torch/numpy bilan (Python 3.14, torch 2.14 CPU). "LLM" o'rnida o'zimiz o'rgatgan so'z darajasidagi kichik GPT; uning ustida API ga o'xshash
Mijoz.yarat()interfeysi quriladi. Bu interfeys parametr nomlari va javob tuzilishini takrorlaydi, lekin katta modellarning xulqi haqida empirik da'vo emas.
2. Nazariya — chuqur tushuntirish
2.1. API parametrlari: 24.9 dagi mexanizmlar
API PARAMETRI 24.9 DAGI MEXANIZM NIMANI BOSHQARADI
temperature logit / T, keyin softmax tekislik (0 -> greedy ga yaqin)
top_p nucleus: massasi >= p eng kichik to'plam dumni kesish (moslashuvchan)
top_k eng katta k ta token dumni kesish (qat'iy)
max_tokens sikl qadamlari soni (yuqori chegara) javob uzunligi, kechikish
stop_sequences shu matn chiqsa, to'xtash format chegarasi
(ba'zi API larda)
frequency_penalty logit -= alfa * soni takrorni kamaytirish
presence_penalty logit -= beta * [soni > 0] yangi mavzuga undash
seed torch.Generator urug'i takrorlanuvchanlik (kafolatsiz)
JAVOBDA:
content - matn (yoki tool chaqiruvi, 25.12)
stop_reason - "end_turn" | "max_tokens" | "stop_sequence" | "tool_use"
usage - input_tokens, output_tokens (narx, 25.2)Muhim farq: API da biz logitlarni ko'rmaymiz. 24.9 da top-p yadrosi hajmini, entropiyani va ehtimollarni to'g'ridan-to'g'ri o'lchadik; API da faqat natija matni va stop_reason bor. Shuning uchun parametr tanlash — tashqaridan o'lchash masalasi: bir nechta sozlamada 100-200 so'rov, to'g'rilik va xilma-xillik o'lchovi, juftlashgan taqqoslash.
API parametrlari — 24.9 dagi dekodlash tugmalarining o'zi; farqi shundaki, ichkarini ko'rmaysiz va faqat natijani o'lchaysiz.
2.2. temperature, top_p va top_k birga
1-MISOL (ro'yxat yozuvchi model, 200 so'rov):
sozlama to'g'ri takror noyob uzunlik
temperature=0 0.0% 100.0% 2.0% 15.5 <- greedy siklga tushdi
temperature=0.5 35.0% 65.0% 100.0% 13.1
temperature=1.0 43.5% 54.5% 100.0% 11.3
temperature=1.5 34.0% 51.5% 99.5% 10.7
T=1.0, top_p=0.9 50.5% 49.5% 100.0% 11.4
T=1.0, top_k=3 45.0% 55.0% 95.0% 11.7
T=1.5, top_p=0.9 48.0% 52.0% 99.0% 10.3
JUFTLASHGAN FARQLAR (to'g'rilik):
T=1.5 + top_p=0.9 - T=1.5 : +0.140, SE 0.027 sezilarli
T=1.0 + top_p=0.9 - T=1.0 : +0.070, SE 0.023 sezilarli
T=0.5 - T=1.0 : -0.085, SE 0.036 sezilarli (!)Ikki kuzatuv. Birinchisi: top_p yuqori haroratning zararini qopladi — T=1.5 da dumdagi xato tokenlar tanlanadi, top_p ularni kesadi (+0.140). Bu 24.9 dagi natijaning API ko'rinishi. Ikkinchisi — kutilmagan: bu vazifada past harorat yomonroq (T=0.5 — T=1.0 dan 0.085 past). Sabab — takror: past T da model eng ehtimolli elementlarni qayta-qayta tanlaydi, T=0 da esa 50 ta so'rovga aynan bir xil, takrorli ro'yxat beradi. "Aniqlik uchun temperatura past bo'lsin" degan qoida faqat bitta to'g'ri javobli vazifalarda to'g'ri; ro'yxat, g'oya, variantlar kerak bo'lganda u zarar keltirishi mumkin.
AMALIY QOIDALAR:
odatda BITTA tugmani o'zgartiring: temperature YOKI top_p
(ba'zi provayderlar ikkalasini birga o'zgartirishni tavsiya etmaydi
yoki cheklaydi - model hujjatini tekshiring)
top_k - kamdan-kam kerak; ko'pincha top_p yetarli
default qiymatlardan boshlang va faqat o'lchov ko'rsatsa o'zgartiringHarorat — vazifaga bog'liq: yagona javobli vazifada past, ro'yxat va xilma-xillik kerak bo'lganda — past harorat takrorga olib kelishi mumkin; har doim o'lchang.
2.3. max_tokens, stop ketma-ketliklari va stop_reason
MAX_TOKENS:
javobning YUQORI CHEGARASI, "buyurtma" emas
model javobni erta tugatsa - kamroq token to'lanadi
chegaraga yetsa - javob ChALA, stop_reason = "max_tokens"
1-MISOL (T=0.5, 200 so'rov):
max_tokens=6 end_turn 0.0%, max_tokens 100.0%
max_tokens=12 end_turn 30.0%, max_tokens 70.0%
max_tokens=30 end_turn 100.0%, max_tokens 0.0%
STOP KETMA-KETLIKLARI:
shu matn paydo bo'lsa - generatsiya to'xtaydi, stop matni javobga KIRMAYDI
stop=[","] -> "anjir" stop_reason = "stop_sequence"
foydali: "faqat birinchi qatorni", shablon chegarasi (masalan, "</javob>")
STOP_REASON QIYMATLARI (Anthropic API):
"end_turn" - model o'zi tugatdi (normal)
"max_tokens" - chegaraga yetdi: javob chala bo'lishi mumkin
"stop_sequence" - stop matnlaridan biri chiqdi
"tool_use" - model vosita chaqirmoqchi (25.12-dars) stop_reason ni har bir javobda tekshiring: "max_tokens" — chala javob, uni foydalanuvchiga yoki keyingi bosqichga (JSON parser, 25.5) uzatmang.
2.4. Chastota va mavjudlik jarimalari
FORMULALAR (ba'zi provayderlarda mavjud):
logit[t] -= frequency_penalty * soni[t] # necha marta chiqqan
logit[t] -= presence_penalty * [soni[t] > 0] # umuman chiqqanmi
soni - SHU javobda allaqachon generatsiya qilingan tokenlar
YON TA'SIR - STRUKTURA TOKENLARI:
vergul, nuqta, qator oxiri, JSON qavslari ham "takrorlanadi"
ularni jazolash -> ro'yxat qisqaradi yoki format buziladi
2-MISOL (T=0.5, 200 so'rov):
sozlama to'g'ri takror elementlar
jarimasiz 35.0% 65.0% 6.0
frequency 1.5 99.5% 0.5% 3.0 <- ro'yxat 2 barobar qisqa
presence 1.5, tinish ozod 88.0% 12.0% 6.0
presence 5.0, tinish ozod 100.0% 0.0% 6.0Bu misolda format buzilmadi, lekin tinish belgilarini jazolash boshqa yo'l bilan "yashirin" zarar keltirdi: model vergulni takrorlashdan qochib, ro'yxatni erta tugatdi — o'rtacha 3.0 element, o'quv ma'lumotida esa 3-8 (o'rtacha 5.5). "To'g'ri" ulushi 99.5% — lekin foydalanuvchi so'ragan narsani (to'liq ro'yxat) olmadi. Tinish belgilari jarimadan ozod qilinganda uzunlik o'z joyiga qaytdi (6.0), takror esa presence 5.0 bilan butunlay yo'qoldi. Ba'zi API larda bunday "ozod" ro'yxat yo'q — u holda jarimani kichik qiymatdan boshlab, uzunlik va format ni ham o'lchab tanlash kerak.
Jarima faqat takrorni emas, hamma takrorlanuvchi tokenni jazolaydi; ta'sirini to'g'rilik, uzunlik va format bilan birga o'lchang.
2.5. Determinizm: temperature=0 nega har doim bir xil emas
NAZARIYADA:
temperature=0 -> har qadamda argmax -> bir xil kirish = bir xil chiqish
AMALDA - FLOAT YIG'INDI TARTIBI:
float32 da (a + b) + c != a + (b + c)
3-misol: (1e8 + (-1e8)) + 1 = 1.0, 1e8 + ((-1e8) + 1) = 0.0
100 000 son yig'indisi: oldinga, teskari, bo'laklab - uch xil natija
GPU da matmul/attention yig'indisini parallel bo'laklarga bo'ladi;
bo'linish batch hajmi, apparat va yadro tanlovi bilan o'zgaradi
server so'rovingizni har safar boshqa batch ga qo'shadi
3-MISOL (40 prompt, greedy, 20 token = 800 qadam):
eng yaqin ikki logit farqi: mediana 0.530, eng kichigi 2.38e-04
usul maks |dlogit| argmax o'zgargan qadam javob o'zgardi
tartib boshqa 4.77e-06 0.00% 0.0%
bfloat16 3.89e-02 0.88% 15.0%
yolg'iz va 40 talik batch: maks |dlogit| 2.38e-06 (CPU da ham 0 emas!)
ZANJIR REAKSIYASI:
bitta qadamda argmax ag'darilsa - keyingi kontekst boshqa -
butun davom boshqa (qadamlarning 0.88% i javoblarning 15% ini o'zgartirdi)Bizning kichik modelda float32 tartib shovqini (~5e-6) 800 qadamda birorta tanlovni ag'darmadi — eng yaqin ikki logit orasidagi farq 2.38e-04 edi. Katta modellarda lug'at yuz minglab token, javoblar minglab token, shuning uchun "deyarli teng" qadamlar ko'p uchraydi va bitlar darajasidagi farq ham ba'zan tanlovni ag'daradi. Past aniqlikdagi hisob (bfloat16 — katta modellarni ishga tushirishda keng tarqalgan) esa shovqinni ming barobar oshiradi va bizning kichik modelda ham javoblarning 15% ini o'zgartirdi.
AMALIY OQIBATLAR:
"temperature=0 -> bir xil javob" ga tayanadigan test mo'rt
seed parametri bo'lsa ham - odatda "iloji boricha", kafolat emas
YECHIMLAR:
testlarda aniq matn emas, XUSUSIYATLAR tekshiriladi
(format, kerakli maydonlar, faktlar - 25.5, 25.10)
kerakli bo'lsa, javobni keshlash yoki saqlash (audit uchun)
baholashda bir necha namuna va o'rtacha temperature=0 — "eng ehtimolli token" degani, "doim bir xil javob" emas; hisob yo'li o'zgarsa, deyarli teng tanlovlar ag'dariladi va butun davom o'zgaradi.
2.6. Kesilgan javobni qayta ishlash
4-MISOL (40 prompt, greedy; NAMUNA narxlar 3 $ / 12 $):
strategiya to'liq chaqiruv kirish chiqish narx/1000 so'rov
e'tiborsiz (8) 0.0% 1.00 8.0 8.0 0.1200 $
qayta urinish (8->16->32) 100.0% 2.00 16.0 21.2 0.3024 $
davom ettirish (8 dan) 100.0% 2.00 24.0 13.2 0.2304 $
yetarli max_tokens (32) 100.0% 1.00 8.0 13.2 0.1824 $
XULOSALAR:
max_tokens ni yetarli qo'yish - eng arzon: faqat yozilgan token to'lanadi
qayta urinish - chala javobning tokenlari BEHUDA ketadi
davom ettirish - chiqish tejaladi, lekin prompt har safar QAYTA to'lanadi
greedy da davom ettirish bir martalik javob bilan 100% bir xilDavom ettirish (javobning boshini qaytarib, "davom et" deb so'rash) model imkoniyatidan uzun javoblar uchun kerak — masalan, modelning maksimal chiqish chegarasidan uzun hujjat. Oddiy holatda esa yechim oddiy: max_tokens ni javob uzunligi taqsimotining dumiga (masalan, 99-persentil) moslang va stop_reason ni tekshiring. Matnga qarab "kesilganmi?" deb taxmin qilish (4-misol, 4-bo'lim) bu formatda ishladi, lekin JSON yoki erkin matnda ishonchli emas — stop_reason bor ekan, uni ishlating.
max_tokens — shift, narx emas: uni yetarli qo'ying va stop_reason == "max_tokens" ni xato holat sifatida qayta ishlang.
2.7. Vazifa turiga qarab parametr tanlash
VAZIFA TEMPERATURE TOP_P MAX_TOKENS BOSHQA
tasniflash, ma'lumot ajratish 0 - 0.2 default kichik, aniq strukturali chiqish 25.5-bob
savol-javob (RAG) 0 - 0.3 default o'rtacha "bilmayman" ruxsat
kod yozish 0 - 0.3 default katta testlar bilan tekshirish
xulosa, tarjima 0.2 - 0.5 default manba x nisbat uzunlik ko'rsatmasi
g'oyalar, variantlar, ro'yxat 0.7 - 1.0 0.9 - 1.0 o'rtacha takrorni o'lchang
ijodiy matn 0.8 - 1.0 0.9 - 1.0 katta bir nechta namuna
HAMMA HOLATDA:
stop_reason ni tekshirish
jadval - boshlang'ich nuqta; yakuniy qiymat - o'z baho to'plamingizda o'lchov
(25.10-dars; qaror qoidasi: "eng yaxshisidan sezilarli yomon bo'lmagan eng sodda")Parametrlar jadvali — boshlang'ich taxmin; yakuniy tanlov o'z vazifangizda juftlashgan o'lchov bilan qilinadi.
2.8. Tuzoqlar
Asosiy tuzoqlar: stop_reason ni tekshirmay chala javobni ishlatish; max_tokens ni "narxni cheklash" uchun juda kichik qo'yish; max_tokens ni "kerakli uzunlik" deb o'ylash (model undan oldin tugatishi mumkin — uzunlikni ko'rsatmada ayting); temperature va top_p ni bir vaqtda ko'r-ko'rona o'zgartirish; "aniqlik uchun temperature=0" ni har vazifaga qo'llash (ro'yxat va variantlarda takrorga olib keladi); jarimani struktura tokenlariga ham qo'llab, formatni yoki uzunlikni buzish; temperature=0 ga tayanib aniq matnni tekshiruvchi testlar yozish; seed ni kafolat deb bilish; kesilgan javobni "qayta urinish" bilan tuzatib, chala tokenlar uchun ikki marta to'lash; stop ketma-ketligi javobga kirmasligini unutish; parametrni bitta namunaga qarab tanlash.
3. Tez ma'lumotnoma
import anthropic
client = anthropic.Anthropic() # ANTHROPIC_API_KEY muhitdan
javob = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024, # yuqori chegara, faqat yozilgani to'lanadi
temperature=0.2, # vazifaga qarab (2.7-jadval)
stop_sequences=["</javob>"], # format chegarasi
messages=[{"role": "user", "content": "..."}],
)
if javob.stop_reason == "max_tokens": # chala javob - xato holat
raise RuntimeError("javob kesildi: max_tokens ni oshiring yoki davom ettiring")
matn = javob.content[0].text
print(javob.usage.input_tokens, javob.usage.output_tokens)
# jarimalar (ba'zi provayderlarda), tinish belgilari ozod
logit = logit - (alfa * soni + beta * (soni > 0)) * niqob # niqob[tinish] = 0
# determinizm: aniq matn emas, xususiyatlarni tekshiring
assert javob_json["holat"] in {"tasdiqlandi", "rad etildi"}Generatsiya parametrlari xulosasi
temperature / top_p / top_k - 24.9 dagi dekodlash tugmalari, tashqaridan o'lchanadi
past T - yagona javobda yaxshi, ro'yxatda takrorga olib kelishi mumkin
max_tokens - shift; stop_reason == "max_tokens" -> chala javob
jarimalar struktura tokenlarini ham jazolaydi
temperature=0 != doim bir xil: float tartib, batch, aniqlik
parametr = o'z baho to'plamingizda juftlashgan o'lchov4. Batafsil misollar
Misollar real torch/numpy bilan (Python 3.14, torch 2.14 CPU). Model — ro'yxat yozishga o'rgatilgan kichik so'z darajasidagi GPT;
Mijoz.yarat()API parametrlari va javob tuzilishini takrorlaydi.
Misol 1 — API uslubidagi parametrlar to'ri
"""API uslubidagi generatsiya: temperature, top_p, top_k, max_tokens, stop va stop_reason."""
import math
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
TOIFALAR = {
"meva": "olma nok uzum anor shaftoli o'rik gilos behi xurmo anjir".split(),
"sabzavot": "sabzi piyoz kartoshka karam bodring pomidor lavlagi turp qalampir baqlajon".split(),
"ichimlik": "choy qahva sut kompot sharbat ayron kefir suv limonad kakao".split(),
"shirinlik": "halva pishiriq tort murabbo novvot parvarda asal konfet shokolad pechenye".split(),
}
L = 32
def royxat(rng):
t = str(rng.choice(list(TOIFALAR)))
n = int(rng.integers(3, 9))
elementlar = [str(x) for x in rng.choice(TOIFALAR[t], n, replace=False)]
return f"<d> ro'yxat : {t} javob : " + " , ".join(elementlar) + " . <end>"
class Blok(nn.Module):
def __init__(self, d, boshlar):
super().__init__()
self.boshlar = boshlar
self.ln1, self.ln2 = nn.LayerNorm(d), nn.LayerNorm(d)
self.qkv = nn.Linear(d, 3 * d)
self.proj = nn.Linear(d, d)
self.ffn = nn.Sequential(nn.Linear(d, 4 * d), nn.GELU(), nn.Linear(4 * d, d))
def forward(self, x):
B, T, d = x.shape
q, k, v = self.qkv(self.ln1(x)).split(d, dim=2)
q, k, v = [t.view(B, T, self.boshlar, -1).transpose(1, 2) for t in (q, k, v)]
o = F.scaled_dot_product_attention(q, k, v, is_causal=True)
x = x + self.proj(o.transpose(1, 2).reshape(B, T, d))
return x + self.ffn(self.ln2(x))
class GPT(nn.Module):
def __init__(self, V, d=48, boshlar=4, qatlamlar=2):
super().__init__()
self.emb = nn.Embedding(V, d)
self.poz = nn.Embedding(L, d)
self.bloklar = nn.Sequential(*[Blok(d, boshlar) for _ in range(qatlamlar)])
self.ln = nn.LayerNorm(d)
self.chiqish = nn.Linear(d, V)
def forward(self, x):
x = x[:, -L:]
h = self.emb(x) + self.poz(torch.arange(x.shape[1]))
return self.chiqish(self.ln(self.bloklar(h)))
def orgat(T, V, seed=0, qadamlar=250, B=32):
torch.manual_seed(seed)
model = GPT(V)
opt = torch.optim.AdamW(model.parameters(), lr=5e-3, weight_decay=0.01)
g = torch.Generator().manual_seed(seed)
for _ in range(qadamlar):
bosh = torch.randint(0, len(T) - L - 1, (B,), generator=g)
w = torch.stack([T[i:i + L + 1] for i in bosh.tolist()])
loss = F.cross_entropy(model(w[:, :-1]).reshape(-1, V), w[:, 1:].reshape(-1))
opt.zero_grad()
loss.backward()
opt.step()
model.eval()
return model
class Mijoz:
"""API ga o'xshash interfeys: parametrlar nomi va javob tuzilishi LLM API laridagidek."""
def __init__(self, model, lugat):
self.model, self.lugat = model, lugat
self.s2i = {w: i for i, w in enumerate(lugat)}
@torch.no_grad()
def yarat(self, promptlar, max_tokens=30, temperature=1.0, top_p=1.0, top_k=None,
stop=None, seed=0):
"""Promptlar ro'yxati -> [{"text", "stop_reason", "usage"}], batch bilan."""
x = torch.tensor([[self.s2i[w] for w in p.split()] for p in promptlar])
n0 = x.shape[1]
g = torch.Generator().manual_seed(seed)
for _ in range(max_tokens):
logit = self.model(x)[:, -1]
if temperature == 0:
keyingi = logit.argmax(-1)
else:
logit = logit / temperature
if top_k is not None:
chegara = logit.topk(top_k, dim=-1).values[:, -1:]
logit = logit.masked_fill(logit < chegara, float("-inf"))
if top_p < 1.0:
tartib, idx = logit.sort(dim=-1, descending=True)
p = torch.softmax(tartib, -1)
tartib = tartib.masked_fill(p.cumsum(-1) - p >= top_p, float("-inf"))
logit = torch.full_like(logit, float("-inf")).scatter(-1, idx, tartib)
keyingi = torch.multinomial(torch.softmax(logit, -1), 1, generator=g)[:, 0]
x = torch.cat([x, keyingi[:, None]], 1)
javoblar = []
for qator in x[:, n0:].tolist():
sozlar, sabab = [], "max_tokens"
for i in qator:
w = self.lugat[i]
if w == "<end>":
sabab = "end_turn"
break
sozlar.append(w)
matn = " ".join(sozlar)
topilgan = [matn.index(s) for s in (stop or []) if s in matn]
if topilgan: # stop matni javobga kirmaydi
sozlar = matn[:min(topilgan)].split()
sabab = "stop_sequence"
break
chiq = len(sozlar) + (1 if sabab != "max_tokens" else 0)
javoblar.append({"text": " ".join(sozlar), "stop_reason": sabab,
"usage": {"input_tokens": n0, "output_tokens": chiq}})
return javoblar
def tahlil(javob, toifa):
"""Ro'yxat to'g'rimi: hamma element shu toifadan, takror yo'q, nuqta bilan tugagan."""
matn = javob["text"]
toza = matn.rstrip(" .")
el = [w for w in toza.split(" , ")] if toza else []
togri_el = all(e in TOIFALAR[toifa] for e in el) and len(el) > 0
takror = len(el) != len(set(el))
return togri_el and not takror and matn.endswith("."), takror, " ".join(el)
def main() -> None:
torch.set_num_threads(1)
rng = np.random.default_rng(0)
matn = " ".join(royxat(rng) for _ in range(3000))
lugat = sorted(set(matn.split()))
s2i = {w: i for i, w in enumerate(lugat)}
mijoz = Mijoz(orgat(torch.tensor([s2i[w] for w in matn.split()]), len(lugat)), lugat)
toifalar = list(TOIFALAR)
promptlar = [f"<d> ro'yxat : {t} javob :" for t in toifalar for _ in range(50)]
toifa_q = [t for t in toifalar for _ in range(50)]
print("=== 1. Bitta so'rov: javob tuzilishi ===")
j = mijoz.yarat(promptlar[:1], temperature=0)[0]
print(f" {j}")
print("\n=== 2. Parametrlar to'ri (200 so'rov: 4 toifa x 50) ===")
print(" sozlama to'g'ri takror noyob o'rt. uzunlik end_turn")
sozlamalar = [("temperature=0", {"temperature": 0}),
("temperature=0.5", {"temperature": 0.5}),
("temperature=1.0", {}),
("temperature=1.5", {"temperature": 1.5}),
("T=1.0, top_p=0.9", {"top_p": 0.9}),
("T=1.0, top_k=3", {"top_k": 3}),
("T=1.5, top_p=0.9", {"temperature": 1.5, "top_p": 0.9})]
togri = {}
for nom, s in sozlamalar:
javoblar = mijoz.yarat(promptlar, seed=1, **s)
t = [tahlil(jv, tq) for jv, tq in zip(javoblar, toifa_q)]
togri[nom] = np.array([x[0] for x in t], dtype=float)
noyob = len({x[2] for x in t}) / len(t)
uz = np.mean([jv["usage"]["output_tokens"] for jv in javoblar])
tugadi = np.mean([jv["stop_reason"] == "end_turn" for jv in javoblar])
print(f" {nom:<22} {togri[nom].mean():>7.1%} {np.mean([x[1] for x in t]):>7.1%} "
f"{noyob:>6.1%} {uz:>14.1f} {tugadi:>9.1%}")
print("\n=== 3. Juftlashgan farq: to'g'rilik (200 so'rov) ===")
for a, b in (("T=1.5, top_p=0.9", "temperature=1.5"), ("T=1.0, top_p=0.9", "temperature=1.0"),
("temperature=0.5", "temperature=1.0")):
d = togri[a] - togri[b]
se = d.std(ddof=1) / math.sqrt(len(d))
print(f" {a} - {b}: {d.mean():+.3f}, SE {se:.3f} -> "
f"{'sezilarli' if abs(d.mean()) > 2 * se else 'sezilarli emas'}")
print("\n=== 4. max_tokens va stop ketma-ketligi ===")
for mt in (6, 12, 30):
javoblar = mijoz.yarat(promptlar, max_tokens=mt, temperature=0.5, seed=1)
sabablar = {s: np.mean([jv["stop_reason"] == s for jv in javoblar])
for s in ("end_turn", "max_tokens")}
print(f" max_tokens={mt:<3}: end_turn {sabablar['end_turn']:>6.1%}, "
f"max_tokens {sabablar['max_tokens']:>6.1%}")
javoblar = mijoz.yarat(promptlar[:3], temperature=0.5, stop=[","], seed=1)
for jv in javoblar:
print(f" stop=[',']: {jv['text']!r:<10} stop_reason={jv['stop_reason']}, chiqish {jv['usage']['output_tokens']} token")
print(" ⭐ stop_reason ni har doim tekshiring: max_tokens - javob chala")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Bitta so'rov: javob tuzilishi ===
{'text': 'gilos , anjir , olma , behi , anor , anjir , nok .', 'stop_reason': 'end_turn', 'usage': {'input_tokens': 6, 'output_tokens': 15}}
=== 2. Parametrlar to'ri (200 so'rov: 4 toifa x 50) ===
sozlama to'g'ri takror noyob o'rt. uzunlik end_turn
temperature=0 0.0% 100.0% 2.0% 15.5 100.0%
temperature=0.5 35.0% 65.0% 100.0% 13.1 100.0%
temperature=1.0 43.5% 54.5% 100.0% 11.3 100.0%
temperature=1.5 34.0% 51.5% 99.5% 10.7 100.0%
T=1.0, top_p=0.9 50.5% 49.5% 100.0% 11.4 100.0%
T=1.0, top_k=3 45.0% 55.0% 95.0% 11.7 100.0%
T=1.5, top_p=0.9 48.0% 52.0% 99.0% 10.3 100.0%
=== 3. Juftlashgan farq: to'g'rilik (200 so'rov) ===
T=1.5, top_p=0.9 - temperature=1.5: +0.140, SE 0.027 -> sezilarli
T=1.0, top_p=0.9 - temperature=1.0: +0.070, SE 0.023 -> sezilarli
temperature=0.5 - temperature=1.0: -0.085, SE 0.036 -> sezilarli
=== 4. max_tokens va stop ketma-ketligi ===
max_tokens=6 : end_turn 0.0%, max_tokens 100.0%
max_tokens=12 : end_turn 30.0%, max_tokens 70.0%
max_tokens=30 : end_turn 100.0%, max_tokens 0.0%
stop=[',']: 'anjir' stop_reason=stop_sequence, chiqish 2 token
stop=[',']: "o'rik" stop_reason=stop_sequence, chiqish 2 token
stop=[',']: 'gilos' stop_reason=stop_sequence, chiqish 2 token
⭐ stop_reason ni har doim tekshiring: max_tokens - javob chalaNima ko'rsatdi: model 3000 ta ro'yxatda o'rgatildi: to'rt toifa (meva, sabzavot, ichimlik, shirinlik), har ro'yxatda 3-8 ta takrorsiz element. yarat() API javobiga o'xshash lug'at qaytaradi: text, stop_reason, usage. Birinchi javobning o'zi muammoni ko'rsatdi: greedy (temperature=0) anjir ni ikki marta yozdi. 2-bo'lim: greedy 200 so'rovga atigi 4 xil ro'yxat berdi (noyob 2.0%), hammasi takrorli — to'g'rilik 0.0%. Harorat oshgan sari takror kamaydi (65.0% → 51.5%), lekin T=1.5 da noto'g'ri toifa elementlari ko'paydi va to'g'rilik 34.0% ga tushdi. Eng yaxshisi T=1.0, top_p=0.9 (50.5%). Juftlashgan farqlar: top_p T=1.5 da +0.140 (SE 0.027), T=1.0 da +0.070 (SE 0.023) — ikkalasi sezilarli; T=0.5 esa T=1.0 dan sezilarli yomon (-0.085, SE 0.036) — past harorat bu vazifada takrorni kuchaytiradi. Umumiy to'g'rilik pastligi kichik modelning cheklovi: u qaysi elementlarni yozib bo'lganini yaxshi "eslamaydi" (2-misolda jarimalar buni tuzatadi). 4-bo'lim: max_tokens=6 da hamma javob kesildi, 12 da 70%, 30 da hech biri. stop=[","] birinchi elementdan keyin to'xtatdi va vergul javobga kirmadi. Bog'liq bo'limlar: 2.1, 2.2, 2.3.
Misol 2 — Takror jarimalari va ularning yon ta'siri
"""Chastota va mavjudlik jarimalari: takrorni kamaytirish va formatni buzmaslik."""
import math
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
TOIFALAR = {
"meva": "olma nok uzum anor shaftoli o'rik gilos behi xurmo anjir".split(),
"sabzavot": "sabzi piyoz kartoshka karam bodring pomidor lavlagi turp qalampir baqlajon".split(),
"ichimlik": "choy qahva sut kompot sharbat ayron kefir suv limonad kakao".split(),
"shirinlik": "halva pishiriq tort murabbo novvot parvarda asal konfet shokolad pechenye".split(),
}
L = 32
def royxat(rng):
t = str(rng.choice(list(TOIFALAR)))
n = int(rng.integers(3, 9))
elementlar = [str(x) for x in rng.choice(TOIFALAR[t], n, replace=False)]
return f"<d> ro'yxat : {t} javob : " + " , ".join(elementlar) + " . <end>"
class Blok(nn.Module):
def __init__(self, d, boshlar):
super().__init__()
self.boshlar = boshlar
self.ln1, self.ln2 = nn.LayerNorm(d), nn.LayerNorm(d)
self.qkv = nn.Linear(d, 3 * d)
self.proj = nn.Linear(d, d)
self.ffn = nn.Sequential(nn.Linear(d, 4 * d), nn.GELU(), nn.Linear(4 * d, d))
def forward(self, x):
B, T, d = x.shape
q, k, v = self.qkv(self.ln1(x)).split(d, dim=2)
q, k, v = [t.view(B, T, self.boshlar, -1).transpose(1, 2) for t in (q, k, v)]
o = F.scaled_dot_product_attention(q, k, v, is_causal=True)
x = x + self.proj(o.transpose(1, 2).reshape(B, T, d))
return x + self.ffn(self.ln2(x))
class GPT(nn.Module):
def __init__(self, V, d=48, boshlar=4, qatlamlar=2):
super().__init__()
self.emb = nn.Embedding(V, d)
self.poz = nn.Embedding(L, d)
self.bloklar = nn.Sequential(*[Blok(d, boshlar) for _ in range(qatlamlar)])
self.ln = nn.LayerNorm(d)
self.chiqish = nn.Linear(d, V)
def forward(self, x):
x = x[:, -L:]
h = self.emb(x) + self.poz(torch.arange(x.shape[1]))
return self.chiqish(self.ln(self.bloklar(h)))
def orgat(T, V, seed=0, qadamlar=250, B=32):
torch.manual_seed(seed)
model = GPT(V)
opt = torch.optim.AdamW(model.parameters(), lr=5e-3, weight_decay=0.01)
g = torch.Generator().manual_seed(seed)
for _ in range(qadamlar):
bosh = torch.randint(0, len(T) - L - 1, (B,), generator=g)
w = torch.stack([T[i:i + L + 1] for i in bosh.tolist()])
loss = F.cross_entropy(model(w[:, :-1]).reshape(-1, V), w[:, 1:].reshape(-1))
opt.zero_grad()
loss.backward()
opt.step()
model.eval()
return model
class Mijoz:
"""API uslubidagi mijoz + chastota va mavjudlik jarimalari."""
def __init__(self, model, lugat):
self.model, self.lugat = model, lugat
self.s2i = {w: i for i, w in enumerate(lugat)}
@torch.no_grad()
def yarat(self, promptlar, max_tokens=30, temperature=1.0, frequency_penalty=0.0,
presence_penalty=0.0, ozod=(), seed=0):
"""logit -= frequency_penalty * soni + presence_penalty * [soni > 0].
ozod - jarimadan ozod tokenlar (masalan, tinish belgilari)."""
x = torch.tensor([[self.s2i[w] for w in p.split()] for p in promptlar])
n0, V = x.shape[1], len(self.lugat)
soni = torch.zeros(len(promptlar), V)
niqob = torch.ones(V)
for w in ozod:
niqob[self.s2i[w]] = 0.0
g = torch.Generator().manual_seed(seed)
for _ in range(max_tokens):
logit = self.model(x)[:, -1]
logit = logit - (frequency_penalty * soni + presence_penalty * (soni > 0)) * niqob
if temperature == 0:
keyingi = logit.argmax(-1)
else:
keyingi = torch.multinomial(torch.softmax(logit / temperature, -1), 1,
generator=g)[:, 0]
soni[torch.arange(len(promptlar)), keyingi] += 1
x = torch.cat([x, keyingi[:, None]], 1)
javoblar = []
for qator in x[:, n0:].tolist():
sozlar, sabab = [], "max_tokens"
for i in qator:
if self.lugat[i] == "<end>":
sabab = "end_turn"
break
sozlar.append(self.lugat[i])
javoblar.append({"text": " ".join(sozlar), "stop_reason": sabab,
"usage": {"input_tokens": n0, "output_tokens": len(sozlar)}})
return javoblar
def tahlil(javob, toifa):
"""(to'g'ri ro'yxatmi, takror bormi, format buzilganmi, elementlar soni)."""
matn = javob["text"]
format_ok = matn.endswith(" .") and javob["stop_reason"] == "end_turn"
tanalar = matn.rstrip(" .").split(" , ") if matn else []
format_ok = format_ok and all(len(t.split()) == 1 for t in tanalar)
el = [t for t in tanalar if t]
takror = len(el) != len(set(el))
togri = format_ok and not takror and all(e in TOIFALAR[toifa] for e in el)
return togri, takror, not format_ok, len(el)
def main() -> None:
torch.set_num_threads(1)
rng = np.random.default_rng(0)
matn = " ".join(royxat(rng) for _ in range(3000))
lugat = sorted(set(matn.split()))
s2i = {w: i for i, w in enumerate(lugat)}
mijoz = Mijoz(orgat(torch.tensor([s2i[w] for w in matn.split()]), len(lugat)), lugat)
toifalar = list(TOIFALAR)
promptlar = [f"<d> ro'yxat : {t} javob :" for t in toifalar for _ in range(50)]
toifa_q = [t for t in toifalar for _ in range(50)]
tinish = (",", ".", "<end>")
print("=== 1. Muammo: past temperaturada takror ===")
for jv in mijoz.yarat(promptlar[::50], temperature=0):
print(f" {jv['text'][:70]}")
print("\n=== 2. Jarimalar (T=0.5, 200 so'rov) ===")
print(" sozlama to'g'ri takror format buzuq elementlar")
sozlamalar = [("jarimasiz", {}),
("frequency 0.5", {"frequency_penalty": 0.5}),
("frequency 1.5", {"frequency_penalty": 1.5}),
("presence 1.5", {"presence_penalty": 1.5}),
("frequency 1.5, tinish ozod", {"frequency_penalty": 1.5, "ozod": tinish}),
("presence 1.5, tinish ozod", {"presence_penalty": 1.5, "ozod": tinish}),
("presence 5.0, tinish ozod", {"presence_penalty": 5.0, "ozod": tinish})]
natija = {}
for nom, s in sozlamalar:
javoblar = mijoz.yarat(promptlar, temperature=0.5, seed=1, **s)
t = np.array([tahlil(jv, tq) for jv, tq in zip(javoblar, toifa_q)], dtype=float)
natija[nom] = t
print(f" {nom:<30} {t[:, 0].mean():>7.1%} {t[:, 1].mean():>7.1%} "
f"{t[:, 2].mean():>13.1%} {t[:, 3].mean():>11.1f}")
buzuq = [jv["text"] for jv in mijoz.yarat(promptlar[:4], temperature=0.5, seed=1,
frequency_penalty=1.5)]
print(f" namuna (frequency 1.5, tinish jarimada): {buzuq[0][:60]!r}")
print("\n=== 3. Juftlashgan farq: to'g'rilik (200 so'rov) ===")
asos = natija["jarimasiz"][:, 0]
for nom in ("frequency 1.5", "presence 1.5, tinish ozod", "presence 5.0, tinish ozod"):
d = natija[nom][:, 0] - asos
se = d.std(ddof=1) / math.sqrt(len(d))
print(f" {nom:<27} - jarimasiz: {d.mean():+.3f}, SE {se:.3f} -> "
f"{'sezilarli' if abs(d.mean()) > 2 * se else 'sezilarli emas'}")
print("\n=== 4. Greedy + jarima (temperature=0) ===")
for nom, s in (("greedy", {}), ("greedy + presence 5.0, ozod",
{"presence_penalty": 5.0, "ozod": tinish})):
javoblar = mijoz.yarat(promptlar[::50], temperature=0, **s)
t = np.array([tahlil(jv, tq) for jv, tq in zip(javoblar, toifalar)], dtype=float)
print(f" {nom:<28} to'g'ri {int(t[:, 0].sum())}/4, takror {int(t[:, 1].sum())}/4: "
f"{javoblar[0]['text'][:48]}")
print(" ⭐ Jarima struktura tokenlariga tegmasin; ta'sirini o'lchab tanlang")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Muammo: past temperaturada takror ===
gilos , anjir , olma , behi , anor , anjir , nok .
sabzi , baqlajon , turp , lavlagi , bodring , qalampir , bodring , sab
kakao , suv , qahva , suv , sharbat , kompot .
tort , murabbo , asal , tort , pishiriq , tort , konfet , pishiriq .
=== 2. Jarimalar (T=0.5, 200 so'rov) ===
sozlama to'g'ri takror format buzuq elementlar
jarimasiz 35.0% 65.0% 0.0% 6.0
frequency 0.5 86.0% 14.0% 0.0% 3.9
frequency 1.5 99.5% 0.5% 0.0% 3.0
presence 1.5 99.5% 0.5% 0.0% 3.5
frequency 1.5, tinish ozod 88.0% 12.0% 0.0% 6.0
presence 1.5, tinish ozod 88.0% 12.0% 0.0% 6.0
presence 5.0, tinish ozod 100.0% 0.0% 0.0% 6.0
namuna (frequency 1.5, tinish jarimada): 'anjir , shaftoli .'
=== 3. Juftlashgan farq: to'g'rilik (200 so'rov) ===
frequency 1.5 - jarimasiz: +0.645, SE 0.034 -> sezilarli
presence 1.5, tinish ozod - jarimasiz: +0.530, SE 0.035 -> sezilarli
presence 5.0, tinish ozod - jarimasiz: +0.650, SE 0.034 -> sezilarli
=== 4. Greedy + jarima (temperature=0) ===
greedy to'g'ri 0/4, takror 4/4: gilos , anjir , olma , behi , anor , anjir , nok
greedy + presence 5.0, ozod to'g'ri 4/4, takror 0/4: gilos , anjir , olma , behi , anor , shaftoli .
⭐ Jarima struktura tokenlariga tegmasin; ta'sirini o'lchab tanlangNima ko'rsatdi: 1-bo'limda greedy to'rt toifaning hammasida takror yozdi (anjir, bodring, suv, tort ikki-uch marta). 2-bo'lim, T=0.5: jarimasiz to'g'rilik 35.0%, takror 65.0%. Chastota jarimasi 1.5 takrorni 0.5% ga tushirdi, to'g'rilik 99.5% — lekin ro'yxat o'rtacha 6.0 dan 3.0 elementga qisqardi: vergul ham jazolandi va model ro'yxatni erta yopdi (namuna: 'anjir , shaftoli .'). Format buzilmadi (0.0%), zarar uzunlikda yashiringan. Tinish belgilari ozod qilinganda uzunlik 6.0 ga qaytdi; presence 1.5 takrorni 12.0% gacha kamaytirdi, presence 5.0 esa butunlay yo'qotdi (100.0% to'g'ri). Juftlashgan farqlar jarimasizga nisbatan hammasi sezilarli (+0.530 dan +0.650 gacha, SE ~0.035). 4-bo'lim: greedy ham jarima bilan to'g'ri ro'yxat berdi (4/4) — takrorlangan anjir o'rniga shaftoli keldi. Bog'liq bo'lim: 2.4.
Misol 3 — Determinizm: float tartibi, batch va aniqlik
"""Determinizm: temperature=0 ham hisob yo'li o'zgarsa boshqa javob berishi mumkin."""
import math
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
TOIFALAR = {
"meva": "olma nok uzum anor shaftoli o'rik gilos behi xurmo anjir".split(),
"sabzavot": "sabzi piyoz kartoshka karam bodring pomidor lavlagi turp qalampir baqlajon".split(),
"ichimlik": "choy qahva sut kompot sharbat ayron kefir suv limonad kakao".split(),
"shirinlik": "halva pishiriq tort murabbo novvot parvarda asal konfet shokolad pechenye".split(),
}
L = 32
def royxat(rng):
t = str(rng.choice(list(TOIFALAR)))
n = int(rng.integers(3, 9))
elementlar = [str(x) for x in rng.choice(TOIFALAR[t], n, replace=False)]
return f"<d> ro'yxat : {t} javob : " + " , ".join(elementlar) + " . <end>"
class Blok(nn.Module):
def __init__(self, d, boshlar):
super().__init__()
self.boshlar = boshlar
self.ln1, self.ln2 = nn.LayerNorm(d), nn.LayerNorm(d)
self.qkv = nn.Linear(d, 3 * d)
self.proj = nn.Linear(d, d)
self.ffn = nn.Sequential(nn.Linear(d, 4 * d), nn.GELU(), nn.Linear(4 * d, d))
def forward(self, x):
B, T, d = x.shape
q, k, v = self.qkv(self.ln1(x)).split(d, dim=2)
q, k, v = [t.view(B, T, self.boshlar, -1).transpose(1, 2) for t in (q, k, v)]
o = F.scaled_dot_product_attention(q, k, v, is_causal=True)
x = x + self.proj(o.transpose(1, 2).reshape(B, T, d))
return x + self.ffn(self.ln2(x))
class GPT(nn.Module):
def __init__(self, V, d=48, boshlar=4, qatlamlar=2):
super().__init__()
self.emb = nn.Embedding(V, d)
self.poz = nn.Embedding(L, d)
self.bloklar = nn.Sequential(*[Blok(d, boshlar) for _ in range(qatlamlar)])
self.ln = nn.LayerNorm(d)
self.chiqish = nn.Linear(d, V)
def forward(self, x):
x = x[:, -L:]
h = self.emb(x) + self.poz(torch.arange(x.shape[1]))
return self.chiqish(self.ln(self.bloklar(h)))
def orgat(T, V, seed=0, qadamlar=250, B=32):
torch.manual_seed(seed)
model = GPT(V)
opt = torch.optim.AdamW(model.parameters(), lr=5e-3, weight_decay=0.01)
g = torch.Generator().manual_seed(seed)
for _ in range(qadamlar):
bosh = torch.randint(0, len(T) - L - 1, (B,), generator=g)
w = torch.stack([T[i:i + L + 1] for i in bosh.tolist()])
loss = F.cross_entropy(model(w[:, :-1]).reshape(-1, V), w[:, 1:].reshape(-1))
opt.zero_grad()
loss.backward()
opt.step()
model.eval()
return model
@torch.no_grad()
def yashirin(model, x):
x = x[:, -L:]
h = model.emb(x) + model.poz(torch.arange(x.shape[1]))
return model.ln(model.bloklar(h))[:, -1]
@torch.no_grad()
def logit_usul(model, h, usul):
"""Bir xil matematik ifoda, turli hisoblash yo'li."""
W, b = model.chiqish.weight, model.chiqish.bias
if usul == "float32":
return h @ W.T + b
if usul == "tartib boshqa": # yig'indi ikki bo'lakda, teskari tartibda
k = h.shape[1] // 2
return (h[:, k:] @ W[:, k:].T + h[:, :k] @ W[:, :k].T) + b
if usul == "bfloat16": # boshqa apparat / aniqlik yo'li
return (h.bfloat16() @ W.bfloat16().T).float() + b
raise ValueError(usul)
@torch.no_grad()
def greedy(model, x, usul, n=20):
for _ in range(n):
keyingi = logit_usul(model, yashirin(model, x), usul).argmax(-1)
x = torch.cat([x, keyingi[:, None]], 1)
return x
def main() -> None:
torch.set_num_threads(1)
print("=== 1. Float yig'indi tartibi ===")
a, b, c = (torch.tensor(v, dtype=torch.float32) for v in (1e8, -1e8, 1.0))
print(f" (1e8 + (-1e8)) + 1 = {((a + b) + c).item():.1f}")
print(f" 1e8 + ((-1e8) + 1) = {(a + (b + c)).item():.1f} (float32 da 1e8 - 1 = -1e8)")
g = torch.Generator().manual_seed(0)
v = torch.randn(100000, generator=g)
oldinga = v.sum().item()
orqaga = v.flip(0).sum().item()
boladi = sum(q.sum().item() for q in v.split(1000))
aniq = v.double().sum().item()
print(f" 100000 son yig'indisi: oldinga {oldinga:.6f}, teskari {orqaga:.6f}, "
f"bo'laklab {boladi:.6f}")
print(f" float64 dagi qiymat {aniq:.6f}; float32 farqlari 0 emas: "
f"{abs(oldinga - aniq):.1e}, {abs(orqaga - aniq):.1e}, {abs(boladi - aniq):.1e}")
print("\n=== 2. Model: bir xil so'rov, turli hisoblash yo'li ===")
rng = np.random.default_rng(0)
matn = " ".join(royxat(rng) for _ in range(3000))
lugat = sorted(set(matn.split()))
s2i = {w: i for i, w in enumerate(lugat)}
model = orgat(torch.tensor([s2i[w] for w in matn.split()]), len(lugat))
promptlar = [f"<d> ro'yxat : {t} javob : {e} ," for t, el in TOIFALAR.items() for e in el]
x = torch.tensor([[s2i[w] for w in p.split()] for p in promptlar])
asos = greedy(model, x, "float32")
print(f" {len(promptlar)} ta prompt, greedy (temperature=0), 20 token")
h_hammasi, qadam_logit = [], []
for t in range(x.shape[1], asos.shape[1]):
h = yashirin(model, asos[:, :t])
h_hammasi.append(h)
qadam_logit.append(logit_usul(model, h, "float32"))
lg = torch.cat(qadam_logit)
top2 = lg.topk(2, -1).values
oraliq = (top2[:, 0] - top2[:, 1]).numpy()
print(f" {len(oraliq)} qadam: eng yaqin ikki logit orasidagi farq - "
f"mediana {np.median(oraliq):.3f}, eng kichigi {oraliq.min():.2e}")
print(" usul maks |dlogit| qadamda argmax o'zgardi javob o'zgardi")
ozgarish = {}
for usul in ("tartib boshqa", "bfloat16"):
boshqa = torch.cat([logit_usul(model, h, usul) for h in h_hammasi])
farq = (boshqa - lg).abs().max().item()
almashdi = (boshqa.argmax(-1) != lg.argmax(-1)).float().mean().item()
javob = greedy(model, x, usul)
ozgardi = (javob != asos).any(1).float().mean().item()
ozgarish[usul] = ozgardi
print(f" {usul:<15} {farq:>13.2e} {almashdi:>25.2%} {ozgardi:>16.1%}")
print("\n=== 3. Batch tarkibi: yolg'iz va 40 talik batch ichida ===")
yolgiz = torch.cat([logit_usul(model, yashirin(model, x[i:i + 1]), "float32")
for i in range(len(x))])
batch = logit_usul(model, yashirin(model, x), "float32")
bf = (yolgiz - batch).abs().max().item()
print(f" maks |dlogit| = {bf:.2e}")
if bf > 0:
print(" hatto CPU da ham: batch hajmi boshqa -> boshqa yadro yo'li -> bitlar farq qiladi")
print(" GPU serverlarda batch hajmi va parallel bo'linish so'rovdan so'rovga o'zgaradi")
print("\n=== 4. Xulosa (natijadan) ===")
kichik = (oraliq < 0.01).mean()
print(f" qadamlarning {kichik:.1%} ida ikki eng yaxshi token farqi 0.01 dan kichik")
if ozgarish["tartib boshqa"] == 0:
print(" float32 tartib shovqini (~1e-6) bu 800 qadamda birorta tanlovni ag'darmadi")
if ozgarish["bfloat16"] > 0:
print(f" bfloat16 shovqini (~1e-2) javoblarning {ozgarish['bfloat16']:.0%} ini o'zgartirdi:"
" bitta ag'darish butun davomni o'zgartiradi")
print(" ⭐ temperature=0 - 'eng ehtimolli token', lekin hisob yo'li o'zgarsa, javob ham o'zgaradi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Float yig'indi tartibi ===
(1e8 + (-1e8)) + 1 = 1.0
1e8 + ((-1e8) + 1) = 0.0 (float32 da 1e8 - 1 = -1e8)
100000 son yig'indisi: oldinga -244.559769, teskari -244.559723, bo'laklab -244.559819
float64 dagi qiymat -244.559764; float32 farqlari 0 emas: 4.9e-06, 4.1e-05, 5.6e-05
=== 2. Model: bir xil so'rov, turli hisoblash yo'li ===
40 ta prompt, greedy (temperature=0), 20 token
800 qadam: eng yaqin ikki logit orasidagi farq - mediana 0.530, eng kichigi 2.38e-04
usul maks |dlogit| qadamda argmax o'zgardi javob o'zgardi
tartib boshqa 4.77e-06 0.00% 0.0%
bfloat16 3.89e-02 0.88% 15.0%
=== 3. Batch tarkibi: yolg'iz va 40 talik batch ichida ===
maks |dlogit| = 2.38e-06
hatto CPU da ham: batch hajmi boshqa -> boshqa yadro yo'li -> bitlar farq qiladi
GPU serverlarda batch hajmi va parallel bo'linish so'rovdan so'rovga o'zgaradi
=== 4. Xulosa (natijadan) ===
qadamlarning 1.6% ida ikki eng yaxshi token farqi 0.01 dan kichik
float32 tartib shovqini (~1e-6) bu 800 qadamda birorta tanlovni ag'darmadi
bfloat16 shovqini (~1e-2) javoblarning 15% ini o'zgartirdi: bitta ag'darish butun davomni o'zgartiradi
⭐ temperature=0 - 'eng ehtimolli token', lekin hisob yo'li o'zgarsa, javob ham o'zgaradiNima ko'rsatdi: float32 da qo'shish assotsiativ emas: (1e8 + (-1e8)) + 1 = 1.0, 1e8 + ((-1e8) + 1) = 0.0 — chunki float32 da -1e8 + 1 yana -1e8 ga yaxlitlanadi. 100 000 ta son yig'indisi oldinga, teskari va bo'laklab uch xil chiqdi (float64 qiymatidan 4.9e-06 — 5.6e-05 farq). 2-bo'lim bir xil model va bir xil kirishda chiqish qatlamini uch yo'l bilan hisobladi. Tartib boshqa bo'lganda logitlar 4.77e-06 gacha farq qildi, lekin 800 qadamning birortasida ham argmax o'zgarmadi — bu modelda eng yaqin ikki logit farqi ham 2.38e-04, ya'ni shovqindan 50 barobar katta. bfloat16 da farq 3.89e-02: qadamlarning atigi 0.88% ida tanlov ag'darildi, lekin javoblarning 15.0% i o'zgardi — bitta ag'darilgan token keyingi butun kontekstni o'zgartiradi. 3-bo'lim — kutilmagan natija: hatto CPU da, bitta ipda, bir xil prompt yolg'iz va 40 talik batch ichida bitlar darajasida farqli logit berdi (2.38e-06) — batch hajmi yadro yo'lini o'zgartiradi. API serverlarida so'rovingiz har safar boshqa batch ga tushadi. Bog'liq bo'lim: 2.5.
Misol 4 — stop_reason: kesilgan javobni qayta ishlash
"""stop_reason: max_tokens bilan kesilgan javobni aniqlash va qayta ishlash strategiyalari."""
import math
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
TOIFALAR = {
"meva": "olma nok uzum anor shaftoli o'rik gilos behi xurmo anjir".split(),
"sabzavot": "sabzi piyoz kartoshka karam bodring pomidor lavlagi turp qalampir baqlajon".split(),
"ichimlik": "choy qahva sut kompot sharbat ayron kefir suv limonad kakao".split(),
"shirinlik": "halva pishiriq tort murabbo novvot parvarda asal konfet shokolad pechenye".split(),
}
L = 32
def royxat(rng):
t = str(rng.choice(list(TOIFALAR)))
n = int(rng.integers(3, 9))
elementlar = [str(x) for x in rng.choice(TOIFALAR[t], n, replace=False)]
return f"<d> ro'yxat : {t} javob : " + " , ".join(elementlar) + " . <end>"
class Blok(nn.Module):
def __init__(self, d, boshlar):
super().__init__()
self.boshlar = boshlar
self.ln1, self.ln2 = nn.LayerNorm(d), nn.LayerNorm(d)
self.qkv = nn.Linear(d, 3 * d)
self.proj = nn.Linear(d, d)
self.ffn = nn.Sequential(nn.Linear(d, 4 * d), nn.GELU(), nn.Linear(4 * d, d))
def forward(self, x):
B, T, d = x.shape
q, k, v = self.qkv(self.ln1(x)).split(d, dim=2)
q, k, v = [t.view(B, T, self.boshlar, -1).transpose(1, 2) for t in (q, k, v)]
o = F.scaled_dot_product_attention(q, k, v, is_causal=True)
x = x + self.proj(o.transpose(1, 2).reshape(B, T, d))
return x + self.ffn(self.ln2(x))
class GPT(nn.Module):
def __init__(self, V, d=48, boshlar=4, qatlamlar=2):
super().__init__()
self.emb = nn.Embedding(V, d)
self.poz = nn.Embedding(L, d)
self.bloklar = nn.Sequential(*[Blok(d, boshlar) for _ in range(qatlamlar)])
self.ln = nn.LayerNorm(d)
self.chiqish = nn.Linear(d, V)
def forward(self, x):
x = x[:, -L:]
h = self.emb(x) + self.poz(torch.arange(x.shape[1]))
return self.chiqish(self.ln(self.bloklar(h)))
def orgat(T, V, seed=0, qadamlar=250, B=32):
torch.manual_seed(seed)
model = GPT(V)
opt = torch.optim.AdamW(model.parameters(), lr=5e-3, weight_decay=0.01)
g = torch.Generator().manual_seed(seed)
for _ in range(qadamlar):
bosh = torch.randint(0, len(T) - L - 1, (B,), generator=g)
w = torch.stack([T[i:i + L + 1] for i in bosh.tolist()])
loss = F.cross_entropy(model(w[:, :-1]).reshape(-1, V), w[:, 1:].reshape(-1))
opt.zero_grad()
loss.backward()
opt.step()
model.eval()
return model
class Mijoz:
"""API ga o'xshash interfeys: parametrlar nomi va javob tuzilishi LLM API laridagidek."""
def __init__(self, model, lugat):
self.model, self.lugat = model, lugat
self.s2i = {w: i for i, w in enumerate(lugat)}
@torch.no_grad()
def yarat(self, promptlar, max_tokens=30, temperature=1.0, top_p=1.0, top_k=None,
stop=None, seed=0):
"""Promptlar ro'yxati -> [{"text", "stop_reason", "usage"}], batch bilan."""
x = torch.tensor([[self.s2i[w] for w in p.split()] for p in promptlar])
n0 = x.shape[1]
g = torch.Generator().manual_seed(seed)
for _ in range(max_tokens):
logit = self.model(x)[:, -1]
if temperature == 0:
keyingi = logit.argmax(-1)
else:
logit = logit / temperature
if top_k is not None:
chegara = logit.topk(top_k, dim=-1).values[:, -1:]
logit = logit.masked_fill(logit < chegara, float("-inf"))
if top_p < 1.0:
tartib, idx = logit.sort(dim=-1, descending=True)
p = torch.softmax(tartib, -1)
tartib = tartib.masked_fill(p.cumsum(-1) - p >= top_p, float("-inf"))
logit = torch.full_like(logit, float("-inf")).scatter(-1, idx, tartib)
keyingi = torch.multinomial(torch.softmax(logit, -1), 1, generator=g)[:, 0]
x = torch.cat([x, keyingi[:, None]], 1)
javoblar = []
for qator in x[:, n0:].tolist():
sozlar, sabab = [], "max_tokens"
for i in qator:
w = self.lugat[i]
if w == "<end>":
sabab = "end_turn"
break
sozlar.append(w)
matn = " ".join(sozlar)
topilgan = [matn.index(s) for s in (stop or []) if s in matn]
if topilgan: # stop matni javobga kirmaydi
sozlar = matn[:min(topilgan)].split()
sabab = "stop_sequence"
break
chiq = len(sozlar) + (1 if sabab != "max_tokens" else 0)
javoblar.append({"text": " ".join(sozlar), "stop_reason": sabab,
"usage": {"input_tokens": n0, "output_tokens": chiq}})
return javoblar
def tahlil(javob, toifa):
"""Ro'yxat to'g'rimi: hamma element shu toifadan, takror yo'q, nuqta bilan tugagan."""
matn = javob["text"]
toza = matn.rstrip(" .")
el = [w for w in toza.split(" , ")] if toza else []
togri_el = all(e in TOIFALAR[toifa] for e in el) and len(el) > 0
takror = len(el) != len(set(el))
return togri_el and not takror and matn.endswith("."), takror, " ".join(el)
# NAMUNA narxlar (FARAZIY), $ / 1M token
N_KIRISH, N_CHIQISH = 3.0, 12.0
def strategiya(mijoz, promptlar, nom, seed=1):
"""Har prompt uchun: (yakuniy javob, chaqiruvlar, kirish tokenlari, chiqish tokenlari)."""
natija = []
for i, p in enumerate(promptlar):
chaqiruv = kirish = chiqish = 0
if nom == "e'tiborsiz (8)":
j = mijoz.yarat([p], max_tokens=8, temperature=0, seed=seed + i)[0]
chaqiruv, kirish, chiqish = 1, j["usage"]["input_tokens"], j["usage"]["output_tokens"]
yakun = j
elif nom == "qayta urinish (8->16->32)":
for mt in (8, 16, 32):
j = mijoz.yarat([p], max_tokens=mt, temperature=0, seed=seed + i)[0]
chaqiruv += 1
kirish += j["usage"]["input_tokens"]
chiqish += j["usage"]["output_tokens"]
if j["stop_reason"] != "max_tokens":
break
yakun = j
elif nom == "davom ettirish (8 dan)":
matn = ""
for _ in range(6):
j = mijoz.yarat([f"{p} {matn}".strip()], max_tokens=8, temperature=0,
seed=seed + i)[0]
chaqiruv += 1
kirish += j["usage"]["input_tokens"]
chiqish += j["usage"]["output_tokens"]
matn = f"{matn} {j['text']}".strip()
if j["stop_reason"] != "max_tokens":
break
yakun = {"text": matn, "stop_reason": j["stop_reason"]}
else: # "yetarli max_tokens (32)"
j = mijoz.yarat([p], max_tokens=32, temperature=0, seed=seed + i)[0]
chaqiruv, kirish, chiqish = 1, j["usage"]["input_tokens"], j["usage"]["output_tokens"]
yakun = j
natija.append((yakun, chaqiruv, kirish, chiqish))
return natija
def main() -> None:
torch.set_num_threads(1)
rng = np.random.default_rng(0)
matn = " ".join(royxat(rng) for _ in range(3000))
lugat = sorted(set(matn.split()))
s2i = {w: i for i, w in enumerate(lugat)}
mijoz = Mijoz(orgat(torch.tensor([s2i[w] for w in matn.split()]), len(lugat)), lugat)
promptlar = [f"<d> ro'yxat : {t} javob : {e} ," for t, el in TOIFALAR.items() for e in el]
print("=== 1. Kesilgan javob qanday ko'rinadi (max_tokens=8) ===")
j = mijoz.yarat(promptlar[:1], max_tokens=8, temperature=0)[0]
print(f" text={j['text']!r}")
print(f" stop_reason={j['stop_reason']!r}, output_tokens={j['usage']['output_tokens']}")
print("\n=== 2. To'rt strategiya (40 prompt, greedy) ===")
print(" strategiya to'liq chaqiruv kirish tok chiqish tok narx/1000 $")
toliq_yakun = {}
for nom in ("e'tiborsiz (8)", "qayta urinish (8->16->32)", "davom ettirish (8 dan)",
"yetarli max_tokens (32)"):
r = strategiya(mijoz, promptlar, nom)
toliq = np.mean([y["stop_reason"] == "end_turn" for y, *_ in r])
ch, ki, cq = (np.mean([x[k] for x in r]) for k in (1, 2, 3))
narx = (ki * N_KIRISH + cq * N_CHIQISH) / 1e6 * 1000
toliq_yakun[nom] = [y["text"] for y, *_ in r]
print(f" {nom:<27} {toliq:>7.1%} {ch:>9.2f} {ki:>11.1f} {cq:>12.1f} {narx:>12.4f}")
print("\n=== 3. Davom ettirish bir martalik javob bilan bir xilmi? ===")
a, b = toliq_yakun["davom ettirish (8 dan)"], toliq_yakun["yetarli max_tokens (32)"]
teng = np.mean([x == y for x, y in zip(a, b)])
print(f" aynan bir xil matn: {teng:.1%} (greedy: kontekst bir xil -> davom bir xil)")
print("\n=== 4. stop_reason o'rniga matnga qarab aniqlash ===")
javoblar = [jv for mt in (6, 9, 32)
for jv in mijoz.yarat(promptlar, max_tokens=mt, temperature=0)]
haqiqiy = np.array([jv["stop_reason"] == "max_tokens" for jv in javoblar])
taxmin = np.array([not jv["text"].endswith(".") for jv in javoblar])
print(f" {len(javoblar)} javob, kesilgani {haqiqiy.mean():.1%}")
print(f" 'nuqta bilan tugamagan' qoidasi: to'g'ri aniqlash {np.mean(taxmin == haqiqiy):.1%}")
ikkala = np.mean(haqiqiy & ~taxmin)
if ikkala > 0:
print(f" {ikkala:.1%} javob nuqta bilan tugagan, lekin baribir kesilgan")
else:
print(" bu formatda qoida ishladi - lekin JSON, kod yoki erkin matnda bunday oddiy belgi yo'q")
print(" ⭐ max_tokens - shift, narx emas: faqat haqiqatan yozilgan tokenlar to'lanadi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Kesilgan javob qanday ko'rinadi (max_tokens=8) ===
text='gilos , anjir , behi , anor ,'
stop_reason='max_tokens', output_tokens=8
=== 2. To'rt strategiya (40 prompt, greedy) ===
strategiya to'liq chaqiruv kirish tok chiqish tok narx/1000 $
e'tiborsiz (8) 0.0% 1.00 8.0 8.0 0.1200
qayta urinish (8->16->32) 100.0% 2.00 16.0 21.2 0.3024
davom ettirish (8 dan) 100.0% 2.00 24.0 13.2 0.2304
yetarli max_tokens (32) 100.0% 1.00 8.0 13.2 0.1824
=== 3. Davom ettirish bir martalik javob bilan bir xilmi? ===
aynan bir xil matn: 100.0% (greedy: kontekst bir xil -> davom bir xil)
=== 4. stop_reason o'rniga matnga qarab aniqlash ===
120 javob, kesilgani 65.8%
'nuqta bilan tugamagan' qoidasi: to'g'ri aniqlash 100.0%
bu formatda qoida ishladi - lekin JSON, kod yoki erkin matnda bunday oddiy belgi yo'q
⭐ max_tokens - shift, narx emas: faqat haqiqatan yozilgan tokenlar to'lanadiNima ko'rsatdi: max_tokens=8 da javob vergul bilan uzildi ('gilos , anjir , behi , anor ,'), stop_reason='max_tokens'. 2-bo'limda to'rt strategiya: e'tiborsiz qoldirish eng arzon (0.1200 $ / 1000 so'rov), lekin birorta ham to'liq javob yo'q. Qayta urinish 100% to'liq, ammo eng qimmat (0.3024 $): kesilgan birinchi urinishning 8 tokeni behuda ketdi va prompt ikki marta yuborildi (chiqish 21.2 token, kerakligi 13.2). Davom ettirish chiqishni tejadi (13.2), lekin prompt va avvalgi qism qayta yuborildi (kirish 24.0) — 0.2304 $. Eng arzon to'liq yechim — boshidan yetarli max_tokens=32: 0.1824 $, chunki model 13 token atrofida o'zi tugatadi va 32 ning qolgani to'lanmaydi. 3-bo'lim: greedy da davom ettirish bir martalik javob bilan 100.0% bir xil — kauzal model uchun "oldingi qism + davom" va "bir martada" bir xil kontekst. 4-bo'lim: 120 javobning 65.8% i kesilgan; bu formatda "nuqta bilan tugamagan" qoidasi 100.0% to'g'ri aniqladi, lekin bu ro'yxat formatining xususiyati — stop_reason esa har qanday formatda ishlaydi. Bog'liq bo'lim: 2.6.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
| "Past temperatura — har doim aniqroq" | 1-misolda T=0.5 T=1.0 dan sezilarli yomon (-0.085); T=0 da to'g'rilik 0.0% |
| "top_p va temperature — bir xil narsa" | T=1.5 da top_p to'g'rilikni +0.140 oshirdi |
| "max_tokens — javob uzunligi" | Yuqori chegara; model ~13 tokenda o'zi tugatdi |
| "Katta max_tokens — qimmat" | Faqat yozilgan tokenlar to'lanadi: 0.1824 $ — eng arzon to'liq yechim |
| "Kesilsa, qayta so'raymiz" | Qayta urinish eng qimmat (0.3024 $) — chala tokenlar behuda |
| "Chastota jarimasi faqat takrorni kamaytiradi" | Ro'yxat 6.0 dan 3.0 ga qisqardi — vergul ham jazolandi |
| "temperature=0 — doim bir xil javob" | bfloat16 shovqini javoblarning 15% ini o'zgartirdi; batch ham logitni o'zgartiradi |
| "Float yig'indisi tartibga bog'liq emas" | (1e8 - 1e8) + 1 = 1, 1e8 + (-1e8 + 1) = 0 |
| "Stop ketma-ketligi javobda qoladi" | Stop matni javobga kirmaydi |
| "Chala javobni matndan bilib olamiz" | Formatga bog'liq; stop_reason — ishonchli manba |
6. Keng tarqalgan xatolar va yechimlari
1. stop_reason tekshirilmaydi
saytga_chiqar(javob.content[0].text) # ⚠️
if javob.stop_reason == "max_tokens": # ✅
raise ChalaJavob(javob.usage.output_tokens)
saytga_chiqar(javob.content[0].text)2. Narxni kichik max_tokens bilan cheklash
javob = client.messages.create(..., max_tokens=100) # ⚠️ chala javoblar
javob = client.messages.create(..., max_tokens=uzunlik_p99) # ✅ + ko'rsatmada uzunlik3. Ro'yxat vazifasida temperature=0
g_oyalar = yarat(prompt, temperature=0) # ⚠️ takror, bir xil
g_oyalar = yarat(prompt, temperature=1.0, top_p=0.9) # ✅ + takror o'lchovi4. Jarima struktura tokenlariga ham
logit -= alfa * soni # ⚠️ vergul ham
logit -= alfa * soni * niqob # ✅ niqob[tinish] = 05. temperature=0 ga tayangan test
assert yarat(prompt, temperature=0) == KUTILGAN_MATN # ⚠️ mo'rt
d = json.loads(yarat(prompt, temperature=0)) # ✅ xususiyatlar
assert d["toifa"] in TOIFALAR and d["summa"] > 06. Kesilganda boshidan qayta so'rash
while j.stop_reason == "max_tokens": # ⚠️ chala tokenlar behuda
j = yarat(prompt, max_tokens=2 * mt)
j = yarat(prompt, max_tokens=yetarli) # ✅ bir chaqiruv7. Temperature va top_p ni birga ko'r-ko'rona
yarat(prompt, temperature=0.3, top_p=0.5, top_k=5) # ⚠️ nima ishladi?
yarat(prompt, temperature=0.3) # ✅ bitta tugma, o'lchov bilan7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 24.9-dars (o'tilgan): greedy, temperature, top-k, top-p,
torch.Generator— bu darsdagi parametrlarning mexanizmi - 24.11-dars (o'tilgan): aralash aniqlik (bfloat16) — determinizm buzilishining bir sababi
- 25.2-dars (o'tilgan):
usageva narx —max_tokensstrategiyalari narxi - 18-qism (o'tilgan): juftlashgan taqqoslash — parametr tanlash
- Keyingi darslar: prompt tuzilishi 25.4-bob, strukturali chiqish — kesilgan JSON xavfi 25.5-bob, retry va xatolarni qayta ishlash 25.6-bob, baho to'plamida parametr tanlash 25.10-bob,
stop_reason == "tool_use"(25.12)
8. Eng yaxshi amaliyotlar
Har javobda
stop_reasonni tekshiring;"max_tokens"ni xato holat deb qayta ishlang.max_tokensni javob uzunligi taqsimotining dumiga moslang; uzunlikni ko'rsatmada ayting.Bitta tugmani o'zgartiring (temperature yoki top_p) va o'lchang.
Harorat tanlashda vazifa turini hisobga oling: yagona javob — past, variantlar — o'rtacha.
Jarimalarni kichik qiymatdan boshlang; to'g'rilik, uzunlik va formatni birga o'lchang.
temperature=0ga tayanadigan testlar o'rniga xususiyatlarni tekshiring.Parametrlarni 100-200 so'rovlik to'plamda juftlashgan taqqoslash bilan tanlang.
Javoblarni (kerak bo'lsa) saqlang — takrorlanuvchanlik uchun yagona ishonchli yo'l.
9. Amaliy topshiriq
Vazifa 1: Bashorat qiling
1. # temperature=0 da namuna olish nimaga aylanadi?
2. # max_tokens=500, model 120 tokenda tugatdi - nechta chiqish tokeni to'lanadi?
3. # stop_reason = "max_tokens" nimani bildiradi?
4. # stop=["\n\n"] bilan javob matnida "\n\n" bo'ladimi?
5. # frequency_penalty vergulga qanday ta'sir qiladi?
6. # 1-misolda nega T=0.5 T=1.0 dan yomon?
7. # float32 da (1e8 + (-1e8)) + 1 va 1e8 + ((-1e8) + 1)?
8. # bitta qadamda argmax ag'darilsa, qolgan javob nima bo'ladi?
9. # kesilgan javobni "qayta urinish" nega qimmat?
10. # davom ettirishda qaysi tokenlar qayta to'lanadi?
11. # ma'lumot ajratish vazifasi uchun taxminiy temperature?
12. # temperature=0 bilan yozilgan regression test nega mo'rt?Javoblar
- Greedy ga (argmax)
- 120 ta
- Model chegaraga yetdi — javob chala bo'lishi mumkin
- Yo'q — stop matni javobga kirmaydi
- Vergul har safar chiqqanda jarimasi oshadi — ro'yxat qisqaradi yoki format buziladi (2-misol:
6.0→3.0) - Past harorat eng ehtimolli elementlarni qayta-qayta tanlaydi — takror oshadi
1.0va0.0- Kontekst o'zgaradi — davom butunlay boshqacha bo'lishi mumkin (0.88% qadam → 15% javob)
- Chala birinchi urinishning chiqish tokenlari va prompt qayta to'lanadi
- Prompt va avvalgi qism (kirish sifatida)
0 - 0.2- Float tartibi, batch va aniqlik tufayli bir xil so'rov boshqa javob berishi mumkin
Vazifa 2: Xatolarni tuzating
1. javob = client.messages.create(model=m, max_tokens=50, messages=xabarlar)
return json.loads(javob.content[0].text)
2. variantlar = [yarat(prompt, temperature=0) for _ in range(5)]
3. logit = logit - 1.5 * soni # takrorga qarshi
4. assert yarat("2+2?", temperature=0) == "Javob: 4."
5. while javob.stop_reason == "max_tokens":
javob = yarat(prompt, max_tokens=javob.usage.output_tokens * 2)Javoblar
1. javob = client.messages.create(model=m, max_tokens=1024, messages=xabarlar)
if javob.stop_reason == "max_tokens":
raise ChalaJavob("JSON kesilgan bo'lishi mumkin")
return json.loads(javob.content[0].text) # + validatsiya (25.5)
2. variantlar = [yarat(prompt, temperature=1.0, top_p=0.9, seed=s) for s in range(5)]
# yoki bitta so'rovda "5 ta turli variant" deb so'rash
3. logit = logit - 1.5 * soni * niqob # niqob[tinish] = 0
# va uzunlik/formatni o'lchash
4. javob = yarat("2+2?", temperature=0)
assert "4" in javob # xususiyat, aniq matn emas
5. javob = yarat(prompt, max_tokens=yetarli) # boshidan yetarli chegara
if javob.stop_reason == "max_tokens": # juda uzun bo'lsa - davom ettirish
javob = davom_ettir(prompt, javob)Vazifa 3: Parametrlar to'ri
Modellang:
- API uslubidagi
yarat()(temperature, top_p, top_k, max_tokens, stop) - 200 so'rov: to'g'rilik, takror, noyob, uzunlik
- Juftlashgan farqlar
max_tokensbo'yichastop_reasontaqsimoti
Vazifa 4: Jarimalar
Modellang:
- Chastota va mavjudlik jarimasi
- Tinish belgilari ozod / ozod emas
- To'g'rilik, takror, uzunlik, format
- Jarimaning eng kichik yetarli qiymatini toping
Vazifa 5: Determinizm
Modellang:
- Float yig'indi tartibi
- Chiqish qatlamini uch yo'l bilan hisoblash
- Eng yaqin ikki logit taqsimoti
- Batch hajmi 1, 8, 64 da logit farqi
Vazifa 6: Kesilgan javob
Modellang:
- To'rt strategiya: e'tiborsiz, qayta urinish, davom ettirish, yetarli chegara
- Chaqiruvlar, kirish/chiqish tokenlari va narx
- Davom ettirish natijasining bir martalik bilan mosligi (greedy va T=0.7 da)
stop_reasonva matn qoidasining aniqligi
Vazifa 7: O'ylash
QA muhandisi aytdi: "Biz LLM ni temperature=0 bilan chaqiramiz, demak u deterministik. 300 ta regression test yozdim — har biri aniq kutilgan matn bilan solishtiradi. Test yiqilsa, demak model yoki prompt buzilgan." Siz nima deysiz?
Javob
Qisqa javob: temperature=0 deterministiklik kafolati emas, shuning uchun aniq matnni solishtiradigan testlar "tasodifan" yiqiladi va jamoa ularga ishonmay qo'yadi. Testlar javobning xususiyatlarini tekshirishi kerak.
1. Nega bir xil emas. 3-misolda float yig'indi tartibi, batch hajmi va hisob aniqligi logitlarni o'zgartirdi. Bizning kichik modelda float32 shovqini tanlovni ag'darmadi, lekin bfloat16 shovqini qadamlarning 0.88% ida ag'darib, javoblarning 15% ini o'zgartirdi. Katta modelda deyarli teng tanlovlar ko'proq, server esa so'rovni har safar boshqa batch ga qo'shadi.
2. Nima tekshiriladi. Strukturali chiqish: JSON sxemaga mosmi, kerakli maydonlar bormi 25.5-bob. Faktlar: javobda to'g'ri raqam/nom bormi. Taqiqlar: shaxsiy ma'lumot yoki taqiqlangan so'z yo'qmi. Format: uzunlik chegarasi, til. Erkin matn uchun — baholovchi (qoidaga asoslangan yoki boshqa model, 25.10).
3. Statistik yondashuv. Muhim testlarda bitta chaqiruv emas, 3-5 chaqiruv va "hammasi o'tdi" yoki "kamida 4/5" mezoni. Prompt o'zgarishini esa butun baho to'plamida juftlashgan taqqoslash bilan baholash.
4. Qachon aniq matn kerak. Agar audit uchun aynan bir xil javob kerak bo'lsa — javobni saqlash va qayta ishlatish; qayta generatsiya qilmaslik.
Tavsiya:
# 1. assert javob == KUTILGAN -> assert xususiyatlar(javob)
# 2. JSON: sxema validatsiyasi (25.5)
# 3. muhim holatlar: 5 chaqiruv, >= 4/5 o'tishi
# 4. stop_reason == "end_turn" ham test shartiMuhandisga javob: "temperature=0 'eng ehtimolli token' degani, 'bir xil javob' emas — float tartibi va server batchlari tufayli matn ba'zan o'zgaradi. Testlarni aniq matndan xususiyatlarga (sxema, faktlar, taqiqlar) o'tkazaylik, shunda yiqilgan test haqiqiy muammoni ko'rsatadi."
Nimani mustahkamlaydi: 2.2, 2.3, 2.4, 2.5, 2.6-bo'limlar.
Xulosa
Bu darsda 24.9 dagi dekodlash tugmalariga API foydalanuvchisi ko'zi bilan qaradik: API uslubidagi yarat() qurdik, parametrlar to'rini, takror jarimalarini, determinizm chegaralarini va kesilgan javoblarni qayta ishlashni o'lchadik.
Eng muhim uch fikr:
Parametrlar vazifaga bog'liq va o'lchab tanlanadi. 1-misolda ro'yxat vazifasida greedy 200 so'rovga 4 xil takrorli ro'yxat berdi (to'g'rilik
0.0%),T=0.5esaT=1.0dan sezilarli yomon (-0.085,SE 0.036) — past harorat takrorni kuchaytirdi. top_p yuqori haroratda to'g'rilikni+0.140oshirdi. 2-misolda chastota jarimasi takrorni yo'qotdi, lekin vergulni ham jazolab ro'yxatni6.0dan3.0elementga qisqartirdi; tinish belgilari ozod qilinganda uzunlik tiklandi.stop_reasonvamax_tokens— javob to'liqligining nazorati.max_tokens=12da javoblarning 70% i kesildi. 4-misolda kesilgan javobni e'tiborsiz qoldirish 0% to'liq natija berdi; qayta urinish eng qimmat (0.3024 $), eng arzon to'liq yechim — yetarlimax_tokens(0.1824 $), chunki faqat yozilgan tokenlar to'lanadi.temperature=0— doim bir xil javob emas. 3-misolda float32 da qo'shish tartibi natijani o'zgartirdi, CPU da ham yolg'iz va batch ichidagi logitlar bitlar darajasida farq qildi (2.38e-06), bfloat16 shovqini esa qadamlarning0.88%ida tanlovni ag'darib, javoblarning15%ini o'zgartirdi. Testlar aniq matnni emas, xususiyatlarni tekshirishi kerak.
Keyingi darsda prompt engineering asoslari: tizim prompti, aniq ko'rsatma, XML teglar bilan tuzilish, few-shot misollarni tanlash, chain-of-thought va uning narxi, prompt shablonlarining xavfsizligi va versiyalash — "sehrli so'zlar" o'rniga o'lchov bilan.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!