You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 55b90ab
Browse filesBrowse the repository at this point in the historyBrowse files
Methodology §14: how the data was loaded (official BIRD dump, not the pandas
loader, and why), the two-engine table, the two bugs a live Postgres exposed,
and a copy-pasteable reproduction. README's Postgres bullet no longer promises
more than was measured. BACKLOG moves the PG data-migration item out of "gated"
into "done" and keeps the honest remainder (sustained-load host, Space cleanup,
external pen-test).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
-**SQLite** (read-only) — target БД по умолчанию: Chinook + 11 BIRD Mini-Dev slices локально (вся eval на SQLite); на live Space — 9 (три самых больших > 100 MB/файл, см. DEPLOY.md).
97
-
-**Postgres 16** — второй backend с genuinely read-only транзакциями (execution-option, не роль-плацебо); запускается локально через `docker-compose.yml` (profile `postgres`), данные грузятся `scripts/load_postgres.py` (`codebase_community` = StackExchange-mini). Read-only enforcement проверяется на живом PG16 в CI. На HF Space не тянется (SQLite-only деплой).
97
+
- **Postgres 16** — второй backend с genuinely read-only транзакциями (execution-option, не роль-плацебо); запускается локально через `docker-compose.yml` (profile `postgres`). **Прогнан, а не только заявлен:** `codebase_community` (StackExchange-mini, 741 646 строк) залит из официального BIRD PG-дампа (`scripts/extract_pg_dump_slice.py`), и тот же пайплайн на BIRD-овском **Postgres-gold** даёт **49.0% EA (24/49)** против 44.9% на SQLite для тех же вопросов, validity 100% — движок переносим. Живой прогон нашёл два бага, невидимых на SQLite (`%` в `LIKE` ронял psycopg-путь; `Decimal` из `numeric` занижал скоринг) — оба починены, см. `docs/03_eval_methodology.md` §14. Read-only enforcement проверяется на живом PG16 в CI. На HF Space не тянется (SQLite-only деплой).
Copy file name to clipboardExpand all lines: docs/03_eval_methodology.md
+62Lines changed: 62 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -409,3 +409,65 @@ uv run python scripts/eval_baseline.py --config E --n 200 --bird-rescue-hints
409
409
94.0% выше human-expert baseline (BIRD paper, 92.96%) на +1.04pp — но это **hint-assisted слой**, кодирующий ответы к конкретным вопросам теста, а не провайдер-уровневая победа. Поэтому он выключен в продукте по умолчанию: живое демо и API отдают уровень 1 (57.5%). `GET /eval/latest` отдаёт именно уровень 1 — число, которого достигает сам API. Разделение на слои показывает и инженерию (воспроизводимые 57.5%), и научную честность (какой слой что даёт).
410
410
411
411
На Arcwise-corrected gold (Jin et al., CIDR/VLDB 2026) — 74.37% (148/199): noise-floor после исправления annotation-ошибок BIRD.
412
+
413
+
---
414
+
415
+
## 14. Postgres: тот же пайплайн на другом движке (2026-07-11)
416
+
417
+
До этой даты «Postgres 16 как второй backend» был заявлен, но **ни разу не прогнан**: read-only-защиту чинили в CI на пустой пробной таблице, а живых данных и живого прогона не было. Заявление проверено — и проверка нашла два дефекта, которые на SQLite не проявляются в принципе.
418
+
419
+
### Как загружены данные
420
+
421
+
BIRD Mini-Dev официально поставляет Postgres-версию: `MINIDEV_postgresql/BIRD_dev.sql` (955 МБ `pg_dump`, все 11 БД **в одну схему `public`**) и `mini_dev_postgresql.json` — gold SQL, переписанный под PG (**312 из 500** запросов отличаются от SQLite-версии: `STRFTIME('%Y', x)` → `TO_CHAR(CAST(x AS TIMESTAMP), 'YYYY')` и т.п.).
422
+
423
+
Заливать дамп целиком нельзя: 75 посторонних таблиц (Formula-1, карточные игры, больничные лаборатории) попали бы в schema-retrieval и подменили задачу. `scripts/extract_pg_dump_slice.py` вырезает одну БД по именам таблиц (они глобально уникальны между 11 БД — свойство закреплено тестом) и валидирует срез: все `CREATE TABLE`, все `COPY`, ни одного FK наружу.
424
+
425
+
**Почему не `scripts/load_postgres.py` (SQLite → pandas → PG).** BIRD-овский PG-gold написан под схему их дампа: идентификаторы свёрнуты в нижний регистр (`displayname`, `posthistory`), даты — настоящий `timestamptz`. Pandas-загрузка воспроизводит CamelCase из SQLite, и gold вида `SELECT DisplayName FROM users` (в PG это `displayname`) просто не нашёл бы колонку. Официальный дамп — то, что делает прогон честным BIRD-раном, а не похожим на него. `load_postgres.py` остаётся правильным инструментом для Chinook и произвольных SQLite-срезов, где PG-gold не существует.
426
+
427
+
`codebase_community` (StackExchange-mini): 8 таблиц, **741 646 строк**, 385 МБ в PG. Сверено с SQLite построчно — совпадает по всем таблицам.
428
+
429
+
### Результат (config E, codestral, hints off — тот же продуктовый пайплайн)
430
+
431
+
Одни и те же 49 вопросов `codebase_community`, два движка, свой gold и свой schema-индекс у каждого:
Согласие движков — **88%** (18 вопросов оба решают верно, 25 оба неверно; 4 только SQLite, 2 только Postgres). Разница в 2 вопроса на n=49 — **шум, а не превосходство**: доверительный интервал здесь ±14 pp. Читать это следует так: **пайплайн переносим — на Postgres он не деградирует**, генерируя PG-диалект (`TO_CHAR`, `::`, `ILIKE`) под PG-схему. Валидность 100% означает, что каждый сгенерированный запрос исполнился на живом сервере.
439
+
440
+
Артефакт: `eval/baselines/postgres_codebase_community_n49.json` (под тем же consistency-гейтом, что и остальные baseline'ы).
441
+
442
+
### Два бага, которые нашёл только живой Postgres
443
+
444
+
Оба сидели в продуктовом коде и оба невидимы на SQLite:
445
+
446
+
1. **`%` в SQL убивал запрос.** `execute_readonly` исполнял SQL через `exec_driver_sql`, который передаёт драйверу (пустой) набор параметров. psycopg говорит на `pyformat`, поэтому начинал искать плейсхолдеры и падал на `LIKE '%variance%'`: *only '%s', '%b', '%t' are allowed as placeholders, got '%v'*. Ломался самый частый шаблон text-to-SQL (LIKE-фильтр) и оператор `%` (modulo) — **и BIRD-овский gold тоже**, так что вопрос нельзя было даже оценить (qids 586/587). Починено: исполнение через DBAPI-курсор вообще без параметров — тогда ни `%` (psycopg), ни `:__` (SQLAlchemy `text()`, BIRD qids 959/989/990) не интерпретируются. Драйверные исключения заворачиваются обратно в `sqlalchemy.exc`, чтобы классификация ошибок не поехала.
447
+
448
+
2.**Скоринг занижал Postgres.** psycopg возвращает `numeric` (любые `AVG`, `SUM`, деление) как `Decimal`, SQLite — как `float`. `_hashable` квантовал к сетке допуска только `float`, а `Decimal` пропускал как есть → верный ответ `Decimal('1.3070996799810359')` не попадал в ту же корзину, что gold `1.307099679981036`, и получал miss. Докстринг обещал «Decimal → float» — строки в коде не было. Из-за этого PG-прогон показывал 40.8% вместо 49.0%: **четыре балла EA съедал баг компаратора, а не модель.**
449
+
450
+
Заметность обоих багов на SQLite — нулевая: sqlite3 не парсит `%` и не возвращает `Decimal`. Это и есть аргумент в пользу того, чтобы прогонять заявленный backend, а не только объявлять его.
`--dialect postgresql` без Postgres-бэкенда для выбранных БД падает с ошибкой: PG-gold, исполненный на SQLite-движке, дал бы не громкую ошибку, а тихо заниженный EA.
Copy file name to clipboardExpand all lines: docs/BACKLOG.md
+9-1Lines changed: 9 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -28,9 +28,17 @@ Docs / hygiene / CI
28
28
- ✅ CI: mypy over `src app scripts`; coverage floor (`--cov-fail-under=85`, currently 91%); aligned on Python 3.13.
29
29
- ✅ `docs/SESSION_HANDOFF.md` un-tracked (kitchen); eval trace moved into methodology §13.
30
30
31
+
## Done (2026-07-11, second pass — the Postgres claim, actually run)
32
+
33
+
- ✅ **PG data load + PG-backed eval.**`codebase_community` (StackExchange-mini, 741 646 rows, 385 MB) loaded into a live Postgres 16 from BIRD's own PG dump via `scripts/extract_pg_dump_slice.py` (the dump ships all eleven databases in one `public` schema; the slice keeps one). Row counts verified against SQLite table by table. The product pipeline then ran on BIRD's **Postgres gold**: **49.0% EA (24/49)** vs 44.9% on SQLite for the same questions, 100% validity, 88% agreement between engines — the engine ports. Artefact: `eval/baselines/postgres_codebase_community_n49.json`; method: `docs/03_eval_methodology.md` §14.
34
+
- ✅ **Two product bugs that only a live Postgres could expose** (both invisible on SQLite):
35
+
-`execute_readonly` ran statements through `exec_driver_sql`, which hands the driver an empty parameter set — psycopg (`pyformat`) then parsed `%` as a placeholder and killed every `LIKE '%x%'` and every `%` modulo, *including BIRD's gold* (qids 586/587 couldn't even be scored). Now executed on a DBAPI cursor with no parameters, so neither `%` (psycopg) nor `:__` (SQLAlchemy `text()`) is interpreted; driver exceptions are re-wrapped into `sqlalchemy.exc` so error classification is unchanged.
36
+
-`_normalise_cell` never converted `Decimal` → `float` (its docstring claimed it did), so Postgres `numeric` results (`AVG`, `SUM`, any division) skipped the float-tolerance grid and correct answers scored misses. Cost 4 EA points on the PG run (40.8% → 49.0%).
37
+
- ✅ SQLite headline unaffected by both fixes: re-measured n=200 → still 57.5%.
38
+
31
39
## Gated (needs a decision or an external host)
32
40
33
-
- ⛔ **Sustained-load / PG data migration.** The 460 MB `codebase_community` (StackExchange) load + a PG-backed eval need a real Postgres host; not runnable on the Windows dev box. Loader + CI read-only proof are in place; the full data load is the remaining step.
41
+
- ⛔ **Sustained-load benchmark.** The data-migration half is done (above); a throughput/latency run under sustained load still wants a host that isn't the Windows dev box.
34
42
- ⛔ **Space cleanup + git history.**`SESSION_HANDOFF.md` is un-tracked now, so future deploys won't republish it; removing it from the live Space and any git-history rewrite are force/deploy actions — owner's call.
35
43
- ⛔ **External pen-test of the public API.** Self-attestation is not a substitute; needs an outside pass.
0 commit comments