Asosiy qismga o'tish

Test to'plamlari: toza, shovqinli va real

23-bob 9 kod bloki 2357 so'z

Oltinchi qism

Oltinchi qism — halol benchmark haqida. Model qanchalik yaxshi ekanini faqat test ko'rsatadi, va test noto'g'ri bo'lsa, butun loyiha noto'g'ri yo'nalishga ketadi. Bu qismning uchta bobi: test to'plamlari qanday tuzilgan (shu bob), modellar qanday adolatli solishtiriladi (24-bob) va xatolar jurnali (25-bob).

Yigirmata to'plam

Tezning testlari — accuracy/suites papkasidagi yigirmata to'plam. Har birida savollar va kutilgan javoblar:

python16 qator
import json
import glob
import pandas as pd

qatorlar = []
for fayl in sorted(glob.glob(str(TEZ / "accuracy/suites/*/questions.json"))):
    nom = Path(fayl).parent.name
    savollar = json.load(open(fayl, encoding="utf-8"))
    tur = "real" if nom.startswith("real_") else "shovqinli" if nom.startswith("noisy_") else "toza"
    qatorlar.append({"to'plam": nom, "tur": tur, "savollar": len(savollar),
                     "savol kerak": sum(s["expect"] == "ask" for s in savollar),
                     "suhbat": sum("history" in s for s in savollar),
                     "bir nechta to'g'ri javob": sum(isinstance(s["expect"], list) and len(s["expect"]) > 1 for s in savollar)})
jadval = pd.DataFrame(qatorlar)
show(jadval, 25)
print(jadval.groupby("tur")["savollar"].sum().to_dict(), "jami:", jadval["savollar"].sum())
Chiqish
{'real': 105, 'shovqinli': 320, 'toza': 320} jami: 745
to'plamtursavollarsavol keraksuhbatbir nechta to'g'ri javob
cash_desktoza604104
depositstoza605103
loanstoza40406
noisy_cash_deskshovqinli604104
noisy_depositsshovqinli605103
noisy_loansshovqinli40406
noisy_realistic_cashshovqinli40460
noisy_realistic_depositsshovqinli40561
noisy_realistic_loansshovqinli40464
noisy_transactionsshovqinli40405
real_banksreal21311
real_credit_clientsreal17410
real_fx_ratesreal14214
real_industryreal13211
real_regionsreal20222
real_retailreal20214
realistic_cashtoza40460
realistic_depositstoza40561
realistic_loanstoza40464
transactionstoza40405

Uch tur:

  • Toza — yettita to'plam, 320 savol, to'rtta sintetik jadval ustida. "realistic_" to'plamlar xuddi shu jadvallarning haqiqiy hayotdagidek sarlavhali nusxasi ustida ("Сумма вклада", "Amount (UZS)").
  • Shovqinli — yettita to'plam, xuddi o'sha 320 savol, lekin harf xatolari va boshqa shovqin bilan.
  • Real — oltita to'plam, 105 savol, haqiqiy jadvallar ustida.

Bitta savol ichida

Har bir savol — kichik JSON yozuv:

python7 qator
savollar = json.load(open(TEZ / "accuracy/suites/deposits/questions.json", encoding="utf-8"))
oddiy = savollar[0]
suhbat = next(s for s in savollar if "history" in s)
print(json.dumps(oddiy, ensure_ascii=False, indent=1)[:500])
print()
print("suhbat ichidagi savol:")
print(json.dumps(suhbat, ensure_ascii=False, indent=1)[:900])
Chiqish
{
 "id": 1,
 "language": "uz_latin",
 "text": "Filiallar bo'yicha omonatlar jami summasini chiqar",
 "expect": [
  {
   "steps": [
    {
     "tool": "group_and_total",
     "args": {
      "group_by": [
       "Филиал"
      ],
      "value_column": "Amount (UZS)",
      "agg": "sum"
     }
    }
   ]
  }
 ]
}

suhbat ichidagi savol:
{
 "id": 51,
 "language": "uz_latin",
 "text": "endi kattasidan boshlab sarala",
 "expect": [
  {
   "steps": [
    {
     "tool": "sort",
     "args": {
      "by": "Amount (UZS)",
      "descending": true
     }
    }
   ]
  }
 ],
 "history": [
  {
   "request": "Filiallar bo'yicha jami summa",
   "answer": {
    "steps": [
     {
      "tool": "group_and_total",
      "args": {
       "group_by": [
        "Филиал"
       ],
       "value_column": "Amount (UZS)",
       "agg": "sum"
      }
     }
    ]
   }
  }
 ]
}
  • text — foydalanuvchi so'rovi, language — tili.
  • expect — kutilgan javob: planlar ro'yxati (bir nechta to'g'ri javob bo'lishi mumkin) yoki "ask".
  • history — suhbat ichidagi savol uchun oldingi so'rov va javob. Test paytida engine avval oldingi javobni bajaradi, model esa oldingi qadamni promptda ko'radi (8-bob).

Baholash 10-bobdagi usul bilan: model plani va har bir kutilgan plan bajariladi, natijalar solishtiriladi. Bittasi mos kelsa — to'g'ri.

Bir nechta to'g'ri javob

Ba'zi so'rovlarni ikki xil ma'noda tushunish mumkin, va ikkalasi ham to'g'ri. Masalan:

python5 qator
real_kurs = json.load(open(TEZ / "accuracy/suites/real_fx_rates/questions.json", encoding="utf-8"))
ikki = next(s for s in real_kurs if isinstance(s["expect"], list) and len(s["expect"]) > 1)
print(ikki["text"])
for reja in ikki["expect"]:
    print("  ", json.dumps(reja["steps"], ensure_ascii=False))
Chiqish
dollar kursi
   [{"tool": "filter", "args": {"column": "G1", "op": "=", "value": "USD"}}]
   [{"tool": "filter", "args": {"column": "G7", "op": "=", "value": "AQSH dollari"}}]
   [{"tool": "filter", "args": {"column": "G9", "op": "=", "value": "US Dollar"}}]
   [{"tool": "filter", "args": {"column": "G6", "op": "=", "value": "Доллар США"}}]

"Dollar kursi" — to'rtta to'g'ri javob: valyuta kodi bo'yicha (USD), yoki o'zbekcha, inglizcha, ruscha nom ustuni bo'yicha. To'rttalasi ham bir xil qatorni beradi. Lekin e'tibor bering: hammasi = bilan, jadvaldagi aniq qiymat bilan. 6-qismdagi xatolar tahlilida tez8 bu savolga G6 contains "dollar" deb javob berdi — ruscha "Доллар США" ichida lotincha "dollar" yo'q, va natija bo'sh. Kutilgan javoblar ro'yxati bunday holatlarni qamraydi — aks holda test to'g'ri javobni xato deb hisoblaydi.

Shovqin

Haqiqiy tahlilchi shoshilib yozadi. Shovqinli to'plamlar toza savollardan kod bilan yasalgan: accuracy/make_noisy.py. Har bir savolga beshta shovqin turidan bittasi qo'llanadi:

python12 qator
qoidalar = json.load(open(TEZ / "accuracy/noise.json", encoding="utf-8"))
print("turlar:", qoidalar["kinds"])

toza = {s["id"]: s for s in json.load(open(TEZ / "accuracy/suites/transactions/questions.json", encoding="utf-8"))}
shovqinli = json.load(open(TEZ / "accuracy/suites/noisy_transactions/questions.json", encoding="utf-8"))
korsatilgan = set()
for s in shovqinli:
    if s["noise"] not in korsatilgan:
        korsatilgan.add(s["noise"])
        print(f"\n[{s['noise']}]")
        print(f"  toza:     {toza[s['id']]['text']}")
        print(f"  shovqinli: {s['text']}")
Chiqish
turlar: ['no_apostrophes', 'lowercase', 'uppercase', 'typo', 'spaces']

[typo]
  toza:     Filiallar bo'yicha jami summani hisobla
  shovqinli: Filiallar bo'iycha jami summani hisobla

[lowercase]
  toza:     Sana ustunidagi formatlarni to'g'irla
  shovqinli: sana ustunidagi formatlarni to'g'irla

[uppercase]
  toza:     Eng ko'p komissiya to'lagan 5 ta mijozni ko'rsat
  shovqinli: ENG KO'P KOMISSIYA TO'LAGAN 5 TA MIJOZNI KO'RSAT

[spaces]
  toza:     O'tgan oyga nisbatan filiallar bo'yicha savdoni solishtir
  shovqinli: O'tgan oyga nisbatan filiallar bo'yicha savdoni  solishtir

[no_apostrophes]
  toza:     Muddati o'tgan kreditlarni ko'rsat
  shovqinli: Muddati otgan kreditlarni korsat

Bir muhim qoida: shovqin qiymatlarga tegmaydi. Agar savolda "Bekor qilindi" yoki "Toshkent" bo'lsa va u plandagi qiymat bo'lsa, harf xatosi u so'zga qo'yilmaydi:

python5 qator
from accuracy.make_noisy import protected_words

namuna = next(s for s in toza.values() if s["expect"] != "ask" and protected_words(s, qoidalar["value_args"]))
print(namuna["text"])
print("himoyalangan so'zlar:", protected_words(namuna, qoidalar["value_args"]))
Chiqish
Bekor qilingan operatsiyalarni olib tashla
himoyalangan so'zlar: {'Bekor', 'qilindi'}

Nega? Chunki qiymatni buzish savolning ma'nosini o'zgartiradi: "Toshkent" o'rniga "Tohskent" — bu endi boshqa savol, va kutilgan javob ham boshqa bo'lishi kerak edi. Shovqin faqat foydalanuvchining o'z so'zlarida.

Real to'plamlar

Eng muhim to'plamlar — real jadvallar ustidagilar. Ular tez9 tayyorlanayotganda yasaldi, va ularning maqsadi bitta: modelni o'zimiz yasamagan jadvallarda sinash.

python6 qator
real_qatorlar = []
for nom in sorted(Path(f).parent.name for f in glob.glob(str(TEZ / "accuracy/suites/real_*/questions.json"))):
    j = json.load(open(TEZ / f"prompt/domains/{nom}/table.json", encoding="utf-8"))
    real_qatorlar.append({"toplam": nom, "jadval qatorlari": j["rows"], "ustunlar": len(j["columns"]),
                          "ustun nomlaridan namuna": ", ".join(c["name"] for c in j["columns"][:4])})
show(pd.DataFrame(real_qatorlar))
toplamjadval qatorlariustunlarustun nomlaridan namuna
real_banks369Banknomi, Aktivsumma, Aktivulushi, Kreditsumma
real_credit_clients30 00025ID, LIMIT_BAL, SEX, EDUCATION
real_fx_rates759G1, G2, G3, G4
real_industry96Korsatkichlarnomi, 01122023mlrdsom, 01122023ulushifoizda, 01032024mlrdsom
real_regions148№, Regions, Total loan portfolio, Total loan portfolio of which: individuals
real_retail541 9098InvoiceNo, StockCode, Description, Quantity

Jadvallar ikki manbadan:

  • O'zbekiston bank statistikasi — ommaga ochiq e'lon qilingan jadvallar: banklar bo'yicha aktiv va kreditlar, hududlar bo'yicha kredit va depozitlar, sohalar bo'yicha ulushlar, valyuta kurslari. Bular — tahlilchi har kuni ko'radigan turdagi fayllar, ularning sarlavhalari, birliklari va "jami" qatorlari bilan.
  • Ikkita mashhur ochiq ma'lumotlar to'plami (UCI Machine Learning Repository): kredit kartasi mijozlari (30 000 qator, kodli ustunlar bilan) va onlayn chakana savdo (yarim milliondan ortiq qator).

Hech birida maxfiy ma'lumot yo'q — hammasi ommaga ochiq. Va ularning ustun nomlari biz yasaydigan jadvallardan butunlay farq qiladi: G1...G9, PAY_0, 01122023mlrdsom, Total loan portfolio of which: individuals.

Hech qachon trainingga kirmaydi

Real to'plamlarning qiymati bitta shartga bog'liq: bu jadvallar trainingda bo'lmasligi kerak. Uchta o'qitilgan modelning training fayllarini tekshiramiz — biror qatorning promptida real jadval nomi bormi:

python8 qator
import re

real_nomlar = {json.load(open(TEZ / f"prompt/domains/{r['toplam']}/table.json", encoding="utf-8"))["name"] for r in real_qatorlar}
nom = re.compile(r'Table "([^"]+)" \(')
for model in ("tez8", "tez9", "tez10"):
    korilgan = {nom.search(json.loads(q)["messages"][0]["content"]).group(1)
                for q in open(Path.home() / f"tez_runs/{model}/data/train.jsonl", encoding="utf-8")}
    print(f"{model}: o'qitishdagi jadvallar {len(korilgan)}, ulardan real jadvallar: {len(korilgan & real_nomlar)}")
Chiqish
tez8: o'qitishdagi jadvallar 14, ulardan real jadvallar: 0
tez9: o'qitishdagi jadvallar 18, ulardan real jadvallar: 0
tez10: o'qitishdagi jadvallar 18, ulardan real jadvallar: 0

Nol. Bu jadvallar model uchun har doim yangi.

Tuzoqlar

Real savollarning ko'pchiligida tuzoq belgisi bor — savol modelning qaysi zaif joyini sinashi:

python12 qator
from collections import Counter

real_savollar = [(Path(f).parent.name, s) for f in sorted(glob.glob(str(TEZ / "accuracy/suites/real_*/questions.json")))
                 for s in json.load(open(f, encoding="utf-8"))]
tuzoqlar = Counter(s.get("trap", "oddiy") for _, s in real_savollar)
korilgan_tur = set()
for toplam, s in real_savollar:
    tur = s.get("trap", "oddiy")
    if tur not in korilgan_tur and tur != "oddiy":
        korilgan_tur.add(tur)
        print(f"{tur:12s} ({tuzoqlar[tur]:2d})  {toplam}: {s['text']}")
print(f"{'oddiy':12s} ({tuzoqlar['oddiy']:2d})")
Chiqish
totals       ( 6)  real_banks: kredit portfeli bo'yicha eng katta 5 ta bank
percent      ( 2)  real_banks: kredit ulushi 5 foizdan yuqori banklar
messy        ( 7)  real_banks: nomi yozilmagan bank bormi
vague        ( 6)  real_banks: banklarni tahlil qil
tool_gap     ( 6)  real_banks: har bir bankning kredit depozit nisbati
groups       ( 1)  real_banks: davlat ulushi bor banklarning krediti
followup     ( 7)  real_banks: faqat kapitali 10000 dan kattalari
codes        ( 3)  real_credit_clients: ayol mijozlar
cryptic      (16)  real_fx_rates: dollar kursi
translation  ( 9)  real_regions: Samarqand viloyati
units        ( 2)  real_regions: kredit portfeli 30 trln dan katta viloyatlar
grand_total  ( 1)  real_regions: respublika bo'yicha jami kredit qancha
returns      ( 2)  real_retail: qaytarilgan tovarlar
oddiy        (37)

Masalan, translation — so'rovda qiymat boshqa tilda ("Samarqand viloyati", jadvalda "Samarkand region"); units — so'rovda birlik boshqacha ("5 trillion", jadval milliardda); codes — ma'nosi yozilmagan kodlar; tool_gap — toollar bilan bajarib bo'lmaydigan so'rov; cryptic — G1 kabi ma'nosiz sarlavhalar.

Kutilgan javoblar ham tekshiriladi

Test xatosi — eng xavfli xato: u yaxshi modelni yomon, yomon modelni yaxshi ko'rsatadi. Shuning uchun har bir kutilgan plan schema ga mos ekani test bilan tekshiriladi — ya'ni model grammar bilan yozishi mumkin bo'lgan javob:

bash2 qator
cd /mnt/c/Users/Admin/Desktop/Offline/spikes/spike2_3_model
PYTHONDONTWRITEBYTECODE=1 "$OLDPWD/.venv/bin/python" -m pytest prompt/test_build.py -q -p no:cacheprovider -k "suites" 2>&1 | tail -1
Chiqish (qaytish kodi 0, 5901 ms)
4 passed, 364 deselected in 3.54s

Lekin schema ga mos bo'lish — hali to'g'ri bo'lish degani emas. Real to'plamlardagi bir nechta kutilgan javob keyinroq bahsli chiqdi: masalan, "код и курс" so'rovida "kod" — harfli kodmi (G1) yoki raqamli kodmi (G2)? Test faqat G1 ni qabul qiladi. Bunday savollar 25-bobda va xatolar tahlilida alohida belgilangan, va ularni o'zgartirish — tahlilchi bilan kelishib qilinadigan qaror.

Chegaralar

Halol bo'lish kerak:

  • Real to'plamlardagi savollarni biz yozganmiz. Jadvallar haqiqiy, savollar — bizning tasavvurimiz. Tahlilchining haqiqiy savollari hali yo'q.
  • 105 ta savol — kam. 21-bobda ko'rdik: bu hajmda ikki model orasidagi besh-olti savollik farqni ham ishonchli ajratib bo'lmaydi.
  • Toza to'plamlar training uslubiga yaqin. Ularning jadvallari trainingda bo'lmagan (aynan bir xil matn ham yo'q — 15-bob), lekin ular bizning uslubimizda yozilgan. Toza to'plamdagi 98 foiz real hayotdagi 98 foizni anglatmaydi; real to'plamdagi raqam haqiqatga yaqinroq.

Xulosa

  • Yigirmata to'plam, 745 savol: toza (320), shovqinli (o'sha 320, shovqin bilan) va real (105).
  • Har bir savolda kutilgan planlar ro'yxati yoki "savol berish kerak"; suhbat savollarida oldingi qadam.
  • Shovqin kod bilan qo'shiladi va qiymatlarga tegmaydi.
  • Real to'plamlar — ommaga ochiq haqiqiy jadvallar; ular hech bir modelning trainingida yo'q. Tuzoq belgilari zaif joylarni alohida o'lchaydi.
  • Kutilgan javoblar schema bo'yicha tekshiriladi, lekin ba'zilari bahsli; savollarni biz yozganmiz va ular kam.

Bu bobni bepul o'qidingiz.

Kitob o'rgatadi, lekin sizning kodingiz nega ishlamaganini ayta olmaydi. Kursda uy vazifangiz tekshiriladi.

Telegramda yozish Narxlar