LoRA va Soup: run1 — o'qitilmagan birinchi model
Beshinchi qism
To'rtinchi qismda training ma'lumoti qanday yasalishini ko'rdik. Beshinchi qism — trainingning o'zi: har bir model, uning sozlamalari va natijasi. Lekin hikoyani halol boshlash kerak: birinchi rejalashtirilgan model — run1 — hech qachon o'qitilmagan. Bu bob — nega, va o'sha qaror keyingi hamma narsani qanday belgilagani haqida.
Avval toollar.
LoRA: modelning kichik bir qismini train qilish
4 milliard parametrli modelni to'liq training — har bir vaznni o'zgartirish — juda ko'p xotira va vaqt talab qiladi. LoRA (Low-Rank Adaptation) boshqa yo'l: asl model vaznlari muzlatiladi, va uning ba'zi qatlamlari yoniga kichik qo'shimcha matritsalar qo'yiladi. Training faqat shu qo'shimchalarni o'zgartiradi.
Qanchalik kichik? Tezning birinchi haqiqiy training logidan bitta qator:
log = (Path.home() / "tez_runs/pilot4b/train.log").read_text(encoding="utf-8", errors="replace").replace("\r", "\n") for qator in log.splitlines(): if "trainable" in qator or "LoRA:" in qator: print(qator.strip(" │"))
LoRA: r=16, alpha=32 LoRA applied: 8,519,680 trainable / 4,214,270,976 total (0.20%) Merge LoRA: soup merge --adapter output
To'rt milliard parametrdan sakkiz yarim million — besh yuzdan biri. Shuning uchun training bitta videokartada sig'adi va soatlar ichida tugaydi. Yana bir qadam: asl model ham 4 bitga siqilgan holda yuklanadi (QLoRA) — xotira yana bir necha barobar kamayadi.
Training tugagach, LoRA qo'shimchalari asl modelga merge qilinadi (qo'shib yuboriladi), va natija — oddiy model fayli. Keyin 6-bobdagi kabi GGUF Q4_K_M ga aylantiriladi. Tahlilchining kompyuterida LoRA ham, training kutubxonalari ham kerak emas.
Soup
Trainingni boshqaradigan dastur — Soup (2-bobdagi tadqiqotda tanlangan). U bitta YAML fayl bilan ishlaydi. run1 uchun tayyorlangan fayl:
print((Path.home() / "tez_runs/run1/soup.yaml").read_text(encoding="utf-8"))
base: Qwen/Qwen3.5-2B
task: sft
modality: text
backend: transformers
data:
train: ./data/train.jsonl
format: chatml
val_split: 0.05
max_length: 4096
train_on_responses_only: true
training:
epochs: 2
lr: 2e-4
batch_size: auto
gradient_accumulation_steps: 4
warmup_ratio: 0.03
quantization: 4bit
save_steps: 200
lora:
r: 16
alpha: 32
dropout: 0.05
target_modules: auto
output: ./output
Asosiy qatorlar:
base— asos model: Qwen3.5-2B.format: chatml— 15-bobdagi qator shakli: tizim, foydalanuvchi, javob.val_split: 0.05— oxirgi 5 foiz tekshirish uchun (15-bobdagi tuzoq).train_on_responses_only— loss (xato) faqat javob tokenlarida hisoblanadi. Model besh ming belgili tizim promptini yodlashga urinmaydi — u faqat to'g'ri javob yozishni o'rganadi.quantization: 4bit— QLoRA.lora: r 16, alpha 32— qo'shimcha matritsalarning o'lchami va kuchi.epochs: 2— ma'lumot ikki marta ko'riladi.
run1 ning ma'lumoti
run1 uchun birinchi partiyadan training fayli yasaldi:
import json qatorlar = [json.loads(q) for q in open(Path.home() / "tez_runs/run1/data/train.jsonl", encoding="utf-8")] savollar = sum(q["messages"][-1]["content"].startswith('{"ask"') for q in qatorlar) print(f"qatorlar: {len(qatorlar):,}, rejalar: {len(qatorlar) - savollar:,}, savollar: {savollar}")
qatorlar: 1,638, rejalar: 1,474, savollar: 164
Soup ning o'z tekshiruvi (soup doctor) muhit va fayl to'g'ri ekanini tasdiqladi. Hammasi tayyor edi.
soup train buyrug'i esa hech qachon berilmadi.
Nega o'qitilmadi
Trainingdan oldin oxirgi o'lchov qilindi: 2B modelning o'zi qayerda turibdi, va undan kattaroq 4B qayerda. Ikkalasi ham o'qitilmagan, bir xil sharoitda, ikki to'plamda:
import pandas as pd for toplam in ("transactions", "loans"): for fayl in ("round3", "round4", "round4b"): xom = pd.read_json(TEZ / f"results/{fayl}_{toplam}.jsonl", lines=True) for model, guruh in xom.groupby("model"): if model in ("qwen3.5-2b", "qwen3.5-4b"): print(f"{fayl:8s} {toplam:13s} {model:11s} {int(guruh['correct'].sum())}/{len(guruh)}")
round3 transactions qwen3.5-2b 22/40 round3 transactions qwen3.5-4b 37/40 round4 transactions qwen3.5-2b 20/40 round4 transactions qwen3.5-4b 36/40 round4b transactions qwen3.5-2b 20/40 round3 loans qwen3.5-2b 25/40 round3 loans qwen3.5-4b 30/40 round4 loans qwen3.5-2b 25/40 round4 loans qwen3.5-4b 37/40 round4b loans qwen3.5-2b 25/40
Qwen3.5-2B: 40 dan 20-25. Qwen3.5-4B: 30 dan 37 gacha — raundga qarab (raundlar orasida nima o'zgargani yozib qo'yilmagan). Va bu — trainingsiz.
O'sha kuni 2B ning xatolari alohida ko'rib chiqildi. Xulosa: 2B o'zbek tilini tushunadi — "filiallar bo'yicha", "olib tashla", "o'tgan oy" so'zlarini to'g'ri ushlaydi. U mantiqda xato qiladi: matnli ustunni jamlaydi, guruhlashni unutadi, ikkinchi filtrni tashlab ketadi. 4B esa xuddi shu o'zbekcha savollarda o'ndan to'qqiz-o'nni to'g'ri bajardi.
Ikki yo'l bor edi:
- 2B ni train qilish — tez, kichik, kuchsiz noutbukka mos. Lekin 25 dan 37 gacha ko'tarilishi kerak, va bu ko'p ma'lumot va ko'p raund degani.
- 4B ni train qilish — allaqachon 30-37 da. Training uning qolgan xatolarini tuzatadi.
Qarorni loyiha muallifi qildi, bitta jumla bilan: hamma modelni emas, bitta modelni mukammal darajaga olib chiqish kerak. Tanlov — Qwen3.5-4B. 2B va kuchsiz noutbuk uchun alohida model keyinga qoldirildi — va hozirgacha qaytilmagan.
Trainingdan oldin nima yetishmadi
4B tanlangandan keyin "trainingdan oldin nima yetishmaydi" degan ro'yxat tuzildi. U o'sha kuni yozilgan, va endi har bir bandiga — bir necha kundan keyin — halol baho berish mumkin:
| # | Yetishmagan narsa | Bugungi holat |
|---|---|---|
| 1 | Tekshiruvchi o'qitiladigan model bilan bir xil — u faqat o'zi biladigan misollarni qoldiradi | Asosiy tekshiruvchi Gemma bo'ldi (14-bob). Lekin qutqarishda yana o'quvchi modeli ishlatildi — muammo qisman qaytdi |
| 2 | Davomli suhbat yo'q | Qo'shildi: "on" maydoni, suhbat ichidagi so'rovlar (8-bob) |
| 3 | Ko'p uchraydigan so'rovlar uchun tool yo'q | Sana oralig'i, bir nechta qiymat, saralash, ulush — qo'shildi. Ikki faylni solishtirish — yo'q |
| 4 | Toza snake_case ustun nomlari |
Sarlavhalarni qayta nomlash qo'shildi (15-bob). Kod uslubidagi nomlar — bugun |
| 5 | Juda toza yozilgan so'rovlar | Shovqin qo'shildi (15-bob). Qisqa so'rovlar — hali yetishmaydi (16-bob) |
| 6 | Uzun prompt sekin — o'qitilgan model qisqa promptda ishlashi mumkin | Qilinmadi |
| 7 | Kattaroq, qattiqroq test va tahlilchining savollari | Real jadvallar ustidagi 105 ta savol — qilindi. Tahlilchining savollari — yo'q |
Ba'zi bandlarni hozirgi fayllar bilan tekshiramiz:
asboblar = {a["name"]: a for a in json.load(open(TEZ / "prompt/tools.json", encoding="utf-8"))} filtr_amallari = asboblar["filter"]["args"]["op"]["enum"] print("sana oralig'i asbobi:", "filter_dates" in asboblar) print("bir nechta qiymat (in):", "in" in filtr_amallari) print("saralash asbobi:", "sort" in asboblar) print("ulush (share):", "share" in asboblar["group_and_total"]["args"]) print("ikki faylni solishtirish asbobi:", any("compare" in n or "match" in n for n in asboblar if n != "period_compare")) tez8 = [json.loads(q) for q in open(Path.home() / "tez_runs/tez8/data/train.jsonl", encoding="utf-8")] uzunlik = sorted(len(q["messages"][0]["content"]) for q in tez8) print(f"tez8 tizim promptining medianasi: {uzunlik[len(uzunlik) // 2]:,} belgi")
sana oralig'i asbobi: True bir nechta qiymat (in): True saralash asbobi: True ulush (share): True ikki faylni solishtirish asbobi: False tez8 tizim promptining medianasi: 5,608 belgi
Oltinchi band haqida alohida. Uzun prompt — 6-bobdagi sovuq javob vaqtining sababi. Fikr shunday edi: o'qitilgan model qoidalar va misollarni allaqachon o'rganib olgan, demak promptdan ularni olib tashlash mumkin. Bu hech qachon sinalmadi — prompt besh ming belgi atrofida qoldi. Sinab ko'rmaganimiz uchun foydali bo'lardimi — bilmaymiz.
run1 dan qolgan saboq
run1 o'qitilmagan bo'lsa ham, u eng arzon saboqni berdi: trainingdan oldin o'lchash. Bir necha soatlik test 2B ni train qilish va qayta o'lchashga ketadigan vaqtni tejadi va yo'nalishni o'zgartirdi. Va trainingdan oldingi "nima yetishmaydi" ro'yxati keyingi bir necha modelning planiga aylandi.
Keyingi bobda birinchi haqiqiy training: pilot4b, va undan keyingi tez3, tez4, tez5.
Xulosa
- LoRA modelning kichik bir qismini o'qitadi: Tez da 4 milliarddan 8.5 million parametr (0.2 foiz). Asl model 4 bitda yuklanadi (QLoRA), natija asl modelga qo'shiladi va GGUF ga aylantiriladi.
- Soup bitta YAML fayl bilan boshqariladi; loss faqat javob tokenlarida hisoblanadi.
- run1 (Qwen3.5-2B, 1 638 qator) tayyorlandi, lekin o'qitilmadi: o'qitilmagan 4B 2B dan ancha kuchli chiqdi, va "bitta modelni mukammal qilish" qarori bilan 4B tanlandi.
- Trainingdan oldingi yetti bandlik ro'yxatdan ko'pi bajarildi; ikki faylni solishtirish, qisqa prompt va tahlilchining savollari — hali yo'q.
Bu bobni bepul o'qidingiz.
Kitob o'rgatadi, lekin sizning kodingiz nega ishlamaganini ayta olmaydi. Kursda uy vazifangiz tekshiriladi.