File size: 25,162 Bytes
942050b d48602c 942050b d48602c 942050b d48602c 942050b d48602c 942050b d48602c 942050b d48602c 942050b c59073b 942050b c59073b 30d7071 942050b 30d7071 942050b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 | # NL→SQL Assistant — методология evaluation + ablation plan
**Дата:** 2026-05-10
**Статус:** active baseline (после CX + KM review v1)
**Сопровождает:** `00_task.md`, `02_architecture_v2.md`
> Этот документ — **главный артефакт портфолио** проекта. Без честной ablation
> с реальными числами проект — «ещё один tutorial с Medium». С ablation —
> демонстрация инженерного процесса, который рекрутёр / Senior+ собеседующий
> распознаёт мгновенно.
---
## 1. Что мы измеряем и почему
### 1.1 Primary metric
**Execution Accuracy (EA)** — доля вопросов, где результат сгенерированного SQL
*равен* результату gold SQL (с order-insensitive comparison для агрегатов без `ORDER BY`).
Источник эталонной реализации: official BIRD evaluation script
(https://github.com/bird-bench/mini_dev → `evaluation_ex.py`).
### 1.2 Secondary metrics (обязательно в отчёте)
| Метрика | Что показывает | Почему важна |
|---|---|---|
| **Schema Recall@k** | Доля вопросов, где все нужные таблицы (из gold SQL) попали в retrieved schema | Если это <60% — никакой LLM не поможет, проблема в RAG |
| **SQL Validity Rate** | % SQL, прошедших sqlglot AST guard | Зрелость pipeline; высокое = generator понимает диалект |
| **Repair Success Rate** | % случаев, когда repair_once починил невалидный SQL | Полезность retry-логики |
| **First-pass EA / Final EA** | EA до repair / после repair | Изолирует вклад repair |
| **Empty-Result Rate** | % выполненных SQL с пустым result-set | Часть error taxonomy |
| **Component Match (F1)** | F1 на AST-компонентах (SELECT cols, WHERE, GROUP BY, ORDER BY, JOIN) | Дебаг — где именно generator расходится с gold |
| **Latency P50 / P95** | End-to-end + per-node breakdown | Operational signal для Senior DE |
| **Cost per query** | Token usage × Mistral pricing | Operational signal |
| **Token usage P50 / P95** | Input + output tokens на вопрос | Контекст-эффективность retrieval |
### 1.3 Что НЕ мерим (явно)
- **Exact Match (EM)** — мусор для NL→SQL, два разных корректных SQL дают разный текст. Не использовать.
- **BLEU/ROUGE на SQL** — не корреллирует с execution correctness.
- **«User satisfaction»** в demo без юзеров — фейковая метрика.
## 2. Datasets
### 2.1 BIRD Mini-Dev (primary)
- **Размер:** 500 Q-SQL примеров (verified от bird-bench.github.io, 2026-05-10).
- **Доступ:** https://github.com/bird-bench/mini_dev
- **Зачем:** публичный leaderboard, можно сравниваться с GPT-4 / Claude / DeepSeek и т.д.
- **Difficulty split:** simple / moderate / challenging (BIRD предоставляет).
- **Dialects:** SQLite (главный), MySQL, PostgreSQL — отчёт по каждому диалекту отдельно.
### 2.2 StackExchange-mini (secondary, demo questions)
- **Источник:** gaming.stackexchange.com dump (~1 GB) ИЛИ trimmed StackOverflow 2023-2024 (posts/users/tags/votes only, ~2-5 GB).
- **20-30 курированных gold questions** с manually-written gold SQL и manual answer review.
- **Зачем:** демонстрация на реальной аналитической схеме, разнообразие форматов ответа (графики, ranking, time-series).
- **Метрика:** EA + manual review (qualitative).
### 2.3 Chinook (smoke only)
- **Размер:** ~1MB, 11 таблиц.
- **Зачем:** sanity check pipeline + первое впечатление в demo, **не портфолио-метрика**.
## 3. Эталонные референсные числа (для калибровки expectations)
Из BIRD Mini-Dev leaderboard (public, актуально на 2026-05-10):
| Модель | SQLite EX | MySQL EX | PostgreSQL EX |
|---|---|---|---|
| GPT-4 (zero-shot) | 47.8% | 40.8% | 35.8% |
| GPT-4 + Table Augmentation | 58.0% | 49.2% | 50.8% |
**Калибровка цели для Codestral solo:**
- **Baseline (week 4):** ≥35-40% EX на SQLite (примерно zero-shot GPT-4 уровень).
- **Stretch (week 8+):** ≥50% EX на SQLite (примерно TA-GPT-4 уровень — это уже серьёзный результат).
- **Hard checkpoint week 3:** EX ≥35% → продолжаем; <35% → scope-down per `02_architecture_v2.md` §12.
## 4. Ablation matrix (центральный артефакт)
### 4.1 Конфигурации
Прогон делается на одном и том же **dev split** (250 примеров из 500 Mini-Dev — детерминированный sample). Shipped production-ладдер — **A → C → D → G**, каждая надстраивается над предыдущей:
| # | Конфигурация | Что включено |
|---|---|---|
| **A** | `full_schema` baseline | Вся схема целиком в prompt (если влезает; иначе truncate). Никакой RAG, никаких few-shot, никакого repair. |
| **C** | `Chroma cards` | Dense retrieval (mistral-embed) топ-N table cards + FK graph traversal. Без few-shot, без repair. |
| **D** | `+ fewshot` | C + top-k few-shot Q→SQL примеров из train split. Без repair. |
| **G** | `+ verify_retry` | D + один verify/repair pass при FAIL validate/execute или empty result. **Финальная shipped конфигурация.** |
> **Config B (BM25 cards) намеренно не shipped.** В пилоте dense retrieval (C) был строго лучше BM25 на тех же top-N; BM25 расширял prompt без recall lift. Enum `Configuration.B_BM25` и `run_config_b` сохранены как `NotImplementedError`, чтобы методология читалась как полный A–E ладдер, но production path не зависит от B. См. `src/nl_sql/eval/runner.py` верхний docstring.
>
> Configs E (repair_once) и F (self-consistency vote) живут отдельно — реализованы для ablation, но не на shipped пути.
### 4.2 Что репортится для каждой конфигурации
Шаблон с реальными числами для финальной shipped конфигурации (G + multi-vote + critique + selfcon + Sonnet bridge + selective fewshot expansion + cross-Groq voting + M-Schema + CHASE-SQL DAC + helallao Perplexity Pro/reasoning multi-model voting + GraceKelly browser-orchestrator + targeted P3.F schema-link hints + archive-sweep / archive-rescore audit; n=200, seed=0, v27 2026-05-24):
```
Configuration G_hybrid+multi-vote+critique+selfcon+sonnet+fewshot5+groq3+
mschema+dac+helallao-pro+helallao-reasoning+gracekelly+
archive+p3f-targeted-hints (final shipped path)
EA (overall): 92.0% (184/200, +44.2pp vs GPT-4 zero-shot 47.8%)
EA (simple): 97.0% (65/67)
EA (moderate): 89.9% (89/99)
EA (challenging): 88.2% (30/34)
EA (SQLite only): 92.0% (BIRD Mini-Dev is SQLite-only)
Voting + targeted rescues: 70/200 (frozen-fail directed retry across vote
buckets + 4 P3.F schema-link hints)
Schema Recall@5: 100.0%
SQL Validity Rate: 100.0%
First-pass / Final EA: 47.0 / 92.0 (codestral A baseline → final)
Latency P50 / P95: ~65 ms cache-hit / dozens of seconds on Sonnet-rescued tier
Cost per query: $0 (Mistral free + Groq free + Perplexity Pro browser bridge)
Audit: scripts/audit_rescore.py → stored 184 / true 184 / 0 mismatches
P3.F acceptance: scripts/p3f_acceptance.py --require-pass → qids 207, 1404,
902, 1531, 894, 1251 all PASS
```
Per-bucket lifts that compose the 92.0% headline:
```
A (codestral full_schema) 47.0% baseline
C (codestral dense_cards + sort) 51.0% +4.0pp
D (codestral dense_fewshot k=3) 55.5% +4.5pp
G (codestral verify-retry) 56.5% +1.0pp
G + Sonnet challenging tier hybrid 57.0% +0.5pp
+ groq voting on filter_or_value 62.0% +5.0pp
+ gpt-oss-20b voting on remaining failures 64.5% +2.5pp
+ row_count_off voting bucket 65.5% +1.0pp
+ grounded-critique directed retry 72.0% +6.5pp
+ Mistral self-consistency 72.5% +0.5pp
+ Sonnet rescue on frozen-fail tail 77.0% +4.5pp (9 rescues, 0 regressions)
+ selective fewshot_top_k=5 on residue 77.5% +0.5pp (qid 1500)
+ cross-Groq voting on residue 79.0% +1.5pp (qids 219+352+366)
+ gpt-oss-20b voting (v9) 80.0% +1.0pp (qids 571+1232)
+ M-Schema XiYan retry on residue (v10) 80.5% +0.5pp (qid 1525)
+ CHASE-SQL divide-and-conquer (v11) 81.0% +0.5pp (qid 1036)
+ helallao Perplexity Pro multi-model voting (v12) 82.0% +1.0pp (qids 672+988)
+ helallao reasoning-mode (grok+gpt-5.2) (v13) 84.0% +2.0pp (qids 407+518+866+1529)
+ kimi-k2-thinking reasoning on v13 residue (v14) 84.5% +0.5pp (qid 1235)
+ helallao Pro triplet retry on v14 residue (v15) 85.0% +0.5pp (qid 173)
+ DAC×reasoning combo on v15 residue (v16) 85.5% +0.5pp (qid 77)
+ post-cooldown gpt-5.2-thinking+DAC (v17) 86.0% +0.5pp (qid 896)
+ helallao gpt-5.2 Pro on v17 residue (v18) 86.5% +0.5pp (qid 989)
+ helallao claude-thinking on v18 residue (v19) 87.0% +0.5pp (qid 743)
+ helallao kimi plain on v19 residue (v20) 87.5% +0.5pp (qid 584)
+ GraceKelly Sonnet 4.6 BIRD-grain on qid 1399 (v21) 88.0% +0.5pp (qid 1399)
+ targeted P3.F schema-link merge (v22) 89.0% +1.0pp (qids 207+1404)
+ archive-sweep qid 1205 (v23) 89.5% +0.5pp (audit-discipline)
+ archive-rescore qid 959 after bind-bug fix (v24) 90.0% +0.5pp (engineering)
+ targeted P3.F hint qid 902 formula_1 (v25) 90.5% +0.5pp (driverStandings.position)
+ targeted P3.F hint qid 1531 debit_card (v26) 91.0% +0.5pp (yearmonth.Consumption)
+ targeted P3.F hints qids 894+1251 (v27) 92.0% +1.0pp (lapTimes.ms + Patient⋈Lab⋈Exam)
```
**Selective fewshot expansion note:** глобальный `fewshot_top_k=5` (вместо
default 3) давал −1pp на n=200 в 2026-05 sessions — extra examples
запутывали codestral на correct cases. На frozen failure set после
Sonnet, тот же лeверь даёт +1 rescue / 0 regressions (`qid=1500` simple,
2026-05-17 v7). Это validates общую гипотезу sprint'а: лeвера которые
вредят глобально могут помогать selective на ranked residue, если
применять с `enable_grounded_critique=True` чтобы re-prompt shape-aware.
Все формулы метрик — см. §5. Полные per-config таблицы — §6 ниже. Чтобы получить эти числа локально:
```powershell
uv run python scripts/eval_baseline.py --config G --n 200 --seed 0 --with-fewshot
uv run python scripts/merge_hybrid_eval.py \
--base eval/reports/<date>/G_dense_fewshot_verify_retry-verify-retry.json \
--override eval/reports/<date>/G_dense_fewshot_verify_retry-sonnet-challenging.json \
--override-difficulty challenging --suffix hybrid-codestral-sonnet
uv run python scripts/error_taxonomy.py eval/baselines/hybrid_n200_v0.json
```
### 4.3 Что должно быть видно из таблицы
Это и есть «инженерный сигнал» в портфолио:
- **A → C:** даёт ли dense retrieval выигрыш над full_schema? (на BIRD да, +4pp — некоторые БД не влезают целиком)
- **C → D:** насколько важен few-shot retrieval? (на BIRD +4.5pp на n=200)
- **D → G:** оправдан ли verify-retry pass? (на BIRD +1.0pp + cures empty-result tail)
- **G → G+Sonnet hybrid:** даёт ли Sonnet на challenging tier дополнительный lift? (+11.5pp на n=200, см. 2026-05-13 run)
Если C → D даёт ≤+1% — **few-shot убирается** как лишняя сложность.
Если D → G даёт ≤+0.5pp — **verify-retry убирается**.
Это и есть честный engineering: каждый компонент имеет measured cost/benefit.
## 5. Train/dev hygiene (предотвращение leakage)
**Главный риск:** использование dev examples как few-shot pool → искусственно завышенный EA.
### 5.1 Hard split
- BIRD Mini-Dev = 500 examples. Этот файл — *evaluation only*.
- Few-shot pool строится **только** из BIRD train split (~9 428 examples).
- Тесты в CI: `test_no_dev_in_fewshot()` грепает `fewshot_qsql` Chroma collection
и убеждается, что ни один embedded вопрос не присутствует в dev IDs.
### 5.2 StackExchange split
- 20-30 курированных gold вопросов **никогда** не попадают в few-shot.
- Если для StackExchange нужны few-shot примеры — используются *других* типов, синтетические или из StackOverflow Data Explorer (с публичных source-ов, не gold).
### 5.3 Документация в README
Явный раздел «Train/Dev split hygiene» с указанием, какой именно train file использовался и checksum (SHA256 в `eval/datasets/SHA256SUMS`).
## 6. CI vs nightly vs full eval
### 6.1 CI (per-PR, должен быть быстрым и детерминированным)
- **Unit tests** на узлы графа с **мокнутым LLM** (LiteLLM mock или собственный fake).
- **5-10 cached smoke examples** через **vcr.py** (запись cassette один раз, replay в CI).
- **sqlglot guard tests** — отдельный набор adversarial-SQL для проверки гарда.
- **Schema indexer tests** — собрать на test fixture (Chinook), проверить recall на 5 эталонных вопросах.
- **Никаких live API calls в CI.**
Цель CI: «pipeline не сломан», не «accuracy измерен».
### 6.2 Nightly / on-demand
- **Полный 500-example прогон BIRD Mini-Dev** через E (финальная конфигурация).
- **diskcache** на ключ `(provider, model, prompt_hash) → response` для дедупликации запросов между запусками.
- **Throttle:** `asyncio.Semaphore(N)` где N = 0.8 × текущий free-tier RPS Mistral. При обнаружении rate-limit → exponential backoff через `tenacity`.
- **Pre-flight quota check** (`eval/check_quota.py`) — если daily limit близко к исчерпанию, batch откладывается.
- Артефакт: HTML-отчёт в `eval/reports/YYYY-MM-DD.html`.
- Тригер: cron (если хватит API quota) или manual `make eval-full`.
**Cost estimate:** см. `02_architecture_v2.md §6.5` — один полный eval-прогон по shipped ладдеру A → C → D → G = ~2000 unique generation calls (после первого прогона повторы = 0 API calls благодаря cache). Дополнительные voting/critique/selfcon/Sonnet-rescue layers — ещё ~600 calls на frozen-fail tail.
### 6.3 Pre-release (manual, перед merge в main или релизом)
- **Полная ablation** (A → G + final shipped path) на dev split.
- **Bakeoff** (3 providers × 30 questions) если есть изменения в provider adapter.
- Обновление главной таблицы в README.
## 7. Business semantics: mini-glossary
NL→SQL чаще всего фейлит на словах-определениях, а не на технических терминах:
«active user», «top tag», «growth», «churn», «engaged customer», «revenue».
Это *определения*, не колонки.
### 7.1 Решение
В `schema_chunks` добавляется section «business hints»:
```
Table: Posts
Columns: ...
Business hints:
- "popular post" = Score > 50
- "recent" = CreationDate > NOW() - INTERVAL '30 days'
- "answered question" = AcceptedAnswerId IS NOT NULL
```
### 7.2 Ablation расширение (optional)
Прогон конфигурации E *с* business hints vs *без* — отчёт, насколько они влияют на EA на StackExchange-mini (на BIRD не релевантно — вопросы там без business jargon).
### 7.3 Limit
Не пытаемся построить полноценный semantic layer (это работа WrenAI и им подобных). 1-3 hint'а на таблицу, ровно столько, чтобы покрыть наиболее частые definitions в gold-вопросах.
## 8. Provider bakeoff
### 8.1 Setup (зафиксированы 2026-05-10, $0 budget hard constraint)
- **30 курированных вопросов** (10 BIRD-style + 10 StackExchange + 10 edge cases).
- **3 провайдера** прогон через идентичный pipeline (E конфигурация):
1. **Mistral `codestral-latest`** (v25.08, default) — Mistral La Plateforme free tier.
2. **`gpt-4o-mini` через GitHub Models** (frontier reference) — `models.inference.ai.azure.com` с GitHub PAT, free tier для personal аккаунтов. Backup: Gemini 2.0 Flash через AI Studio.
3. **Ollama `qwen2.5-coder:7b-instruct`** (Q4_K_M ≈ 4.7 GB, default Ollama quant) — fits 16 GB RAM.
**Опциональный 4-й слот** (для отдельных experiments, не в default README таблице):
- `defog/sqlcoder-7b-2` — SQL-specialized, добавляется через `config/providers.yml`. Подходит как "best local SQL signal" в дополнение к qwen2.5-coder.
**Не используются** (зафиксировано — для воспроизводимости):
- `qwen2.5-coder:14b` — 9 GB RAM, **тесно** на 16 GB system при запущенных Postgres+Chroma.
- `qwen2.5-coder:32b` — 20 GB RAM, **не помещается** в 16 GB вообще.
- Frontier альтернативы (Claude/Gemini) — оставлены на будущие итерации, не блокируют v1 portfolio piece.
### 8.2 Что в отчёте
| Provider | EA | Validity Rate | Latency P50 | Cost / 30q |
|---|---|---|---|---|
| Mistral `codestral-latest` | XX% | XX% | X.Xs | $0 (Mistral free tier + диск-кэш) |
| `gpt-4o-mini` (GitHub Models) | XX% | XX% | X.Xs | $0 (GitHub Models free tier) |
| Ollama `qwen2.5-coder:7b` | XX% | XX% | X.Xs | $0 (электричество) |
Плюс **slicing per question**: какая модель ошиблась где.
### 8.3 Что это даёт портфолио
Превращает «почему Mistral?» из вкусовщины в *измеренный trade-off*:
«Codestral даёт 86% от GPT-4 quality за 1/8 стоимости» (или какой бы там результат ни был).
## 9. Operational metrics dashboard
### 9.1 Минимально (Langfuse-only)
В Langfuse:
- per-trace breakdown: token usage, latency, model, cost.
- session view: цепочки вопросов одного юзера.
- error rate за период.
### 9.2 Не делаем
- Prometheus dashboard (фейковая нагрузка для solo).
- OpenTelemetry exporter (не интегрируется ни во что в demo).
- Custom Grafana board.
Всё это — overhead без сигнала.
## 10. Reporting (что попадает в README)
Главная таблица в README проекта:
```markdown
## Results
### Execution Accuracy on BIRD Mini-Dev (n=200, SQLite, seed=0)
| Configuration | EA (overall) | Simple | Moderate | Challenging |
|-------------------------------------------------|-------------|--------|----------|-------------|
| A: full_schema (codestral) | 47.0% | 64.2% | 43.4% | 29.4% |
| C: dense_cards (codestral + sort) | 51.0% | 67.2% | 47.5% | 32.4% |
| D: dense_fewshot (codestral, k=3 BIRD train) | 55.5% | 70.1% | 51.5% | 35.3% |
| G: + verify_retry (codestral) | 56.5% | 71.6% | 53.5% | 38.2% |
| G + Sonnet challenging hybrid | 57.0% | 71.6% | 53.5% | 38.2% |
| + multi-vote + grounded-critique + selfcon | 72.5% | 86.6% | 70.7% | 55.9% |
| + Sonnet rescue on frozen-fail tail | 77.0% | 88.1% | 74.7% | 61.8% |
| + selective fewshot_top_k=5 on residue | 77.5% | 89.6% | 74.7% | 61.8% |
| **+ cross-Groq llama3.3-70b + qwen3 voting (final)** | **79.0%** | **91.0%** | **75.8%** | **64.7%** |
| Reference: GPT-4 zero-shot (BIRD paper) | 47.8% | — | — | — |
| Reference: paid SOTA CHESS/Distillery 2024 | 73–76% | — | — | — |
Final shipped configuration matches `eval/reports/2026-05-17/hybrid-vote-critique-selfcon-sonnet-fewshot5-groq3-v8.json` — see also memory note `project_nl_sql_quality_push`.
Config B (BM25 cards) is intentionally absent from the shipped pipeline — dense retrieval (config C) was strictly superior in pilot runs and BM25 would only widen the prompt with no recall lift. `Configuration.B_BM25` enum and `run_config_b` (NotImplementedError) are kept so the A–E ladder reads as documented, but the production path is A → C → D → G → hybrid → voting/critique/selfcon → Sonnet rescue.
### Provider Bakeoff (chinook smoke, n=60, configuration G)
| Provider | EA | Validity | P50 latency | Cost / 60q |
|------------------------|---------|----------|-------------|------------|
| Mistral codestral | 100% | 100% | <1 s | $0 |
| Claude Sonnet 4.6 (PPL browser) | n/a (eval-only on BIRD challenging) | — | ~30 s | $0 |
| Groq Llama 3.3 70B | partial (JSON-strict failures) | 40% | 1.5 s | $0 |
| Ollama qwen2.5-coder | not benchmarked at scale (local-only) | — | — | $0 |
```
Это **не** «выглядит как туториал». Это выглядит как лабораторный отчёт DE.
## 11. Risk-mitigations cross-ref
Связь с разделом 13 в `02_architecture_v2.md`:
| Риск | Митигация в этом документе |
|---|---|
| Schema retrieval recall <60% | §1.2 (Schema Recall@k как primary secondary metric); §4 (configuration B/C явно выделяет проблему) |
| Benchmark leakage | §5 hard split + CI test |
| Business semantics gap | §7 mini-glossary |
| Repair-loop делает confident-wrong SQL | §1.2 (First-pass vs Final EA репортится отдельно — видно цена repair) |
| codestral-latest version drift | §8 bakeoff фиксирует snapshot для повторяемости |
| Eval flakiness в CI | §6.1 vcr.py + cached smoke только |
## 12. Definition of Done для eval-стрима
- [ ] BIRD Mini-Dev (500) downloaded + checksummed
- [ ] Train split (BIRD train) загружен и явно отделён от dev
- [ ] CI test `test_no_dev_in_fewshot()` написан и проходит
- [ ] Ablation runner работает на 5 конфигурациях (A → E)
- [ ] Все метрики из §1.2 collected per-configuration
- [ ] Slicing by difficulty + dialect работает
- [ ] HTML-отчёт генерируется (`eval/reports/YYYY-MM-DD.html`)
- [ ] CI smoke-eval с vcr.py (5-10 examples) green
- [ ] Bakeoff на 30 вопросов × 3 providers работает
- [x] README результат-таблицы заполнены реальными числами (2026-05-12)
- [ ] Hard checkpoint week 3 пройден (EA ≥35% или scope-down принят)
|