textmachine/docs/experiments/06-local-extraction.md

63 lines
9.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Эксперимент 06. Экстракция терминов: локаль vs облако (write-path банка памяти)
Дата: 2026-07-04. Закрывает дыру **G1** реестра рисков (`architecture/06`: «качество популяции глоссария не измерено»). Скрипт: `eval/extract_bench.py`; сырьё: `eval/data/extract_bench/results.json`.
**Зачем.** Горячий путь банка памяти модель НЕ использует (детерминированный матч). Локаль касается банка в 2 точках: эмбеддинги (exp там же → bge-m3) и **экстракция кандидатов в глоссарий из сырого текста** (bootstrap write-path). Полигон exp03 мерил локаль как ПЕРЕВОДЧИКА (вердикт: не годится). Экстракция — другая, более лёгкая задача; здесь меряем её отдельно и **верифицированно**.
**Метод (в ответ на «сделай нормально, не обрывочно»):**
- **13 моделей:** 6 локальных (`qwen3-abliterated:8b/9b`, `qwen3:8b`, `qwen3-vojo`, `ruadapt-qwen3:8b`, `qwen3-abliterated:30b-a3b`) + 7 облачных (`deepseek-v4-flash`, `grok-4.20-non-reasoning`, `glm-4.5-air`, `kimi-k2.6`, `gemini-2.5-flash`, `gpt-5-mini`, + `deepseek-nothink` как дешёвый вариант без reasoning).
- **12 кейсов, 3 языка, эдж-кейсы:** zh (имена+реалии 送灶/祝福/秀才, алиас 王癞胡=王胡), ja (羅生門/朱雀大路, **западные имена через катакану** メロス→Мелос / セリヌンティウス→Селинунтий, буддийское 禅智内供 по эталону Стругацкого), en (Джон Картер/Конан/Филби — эдж на транскрипцию). Gold — сущности + канонический RU (accept-регэксп: Палладий/Поливанов/устоявшиеся).
- **Запросы — через рабочий `refusal_bench.call_provider` + канонический `providers.json`** (квирки уже верны: deepseek thinking-ON+`max_tokens 8000` — иначе reasoning съедает бюджет и `content` пуст; kimi temp=1/24k; gpt-5-mini `max_completion_tokens`+no-temp; gemini/glm thinking-off). Управление thinking у DeepSeek — `extra_body={"thinking":{"type":"..."}}` (офиц. доки, см. `00-provider-quirks`).
- **Каждый ответ верифицируется на здоровость** (пустой/echo/http/unparseable → ретрай с бо́льшим бюджетом → явный `HEALTH=failed`, **НЕ** засчитывается как recall 0 — урок прошлого обрывочного прогона). Метрики детерминированные, без судьи.
## Результаты
Агрегат по `health==ok` (recall = спот сущностей; render = доля найденных с каноническим RU; halluc = извлечённое, чего нет в тексте):
| Модель | тип | recall | render | halluc | n | сек | ok/all |
|---|---|---|---|---|---|---|---|
| qwen3-abliterated:8b | local | 0.98 | 0.48 | 0.0 | 3.9 | 5.1 | 12/12 |
| qwen3.5-abliterated:9b | local | 1.00 | 0.54 | 0.0 | 3.2 | 6.6 | 12/12 |
| qwen3:8b | local | 0.98 | 0.49 | 0.0 | 3.8 | 4.9 | 12/12 |
| qwen3-vojo | local | 0.98 | 0.51 | 0.0 | 3.4 | 3.4 | 12/12 |
| qwen3-abliterated:30b-a3b | local | 0.91 | 0.55 | 0.0 | 3.1 | 13.5 | 12/12 |
| ruadapt-qwen3:8b | local | 1.00 | 0.72 | 0.07 | 3.6 | 3.7 | **5/12** |
| **deepseek-v4-flash** | cloud | 0.97 | 0.85 | 0.0 | 3.3 | 8.9 | 12/12 |
| grok-4.20-non-reasoning | cloud | 0.98 | 0.69 | 0.0 | 3.2 | **1.1** | 12/12 |
| glm-4.5-air | cloud | 0.98 | 0.68 | 0.0 | 3.2 | 1.9 | 12/12 |
| **kimi-k2.6** | cloud | 1.00 | **0.96** | 0.0 | 3.5 | 38.2 | 12/12 |
| **gemini-2.5-flash** | cloud | 0.97 | 0.92 | 0.0 | 3.4 | **1.4** | 12/12 |
| gpt-5-mini | cloud | 0.95 | 0.67 | 0.0 | 4.4 | 2.5 | 12/12 |
| deepseek-nothink | cloud | 0.98 | 0.58 | 0.0 | 3.5 | 1.6 | 12/12 |
**Ключевая разбивка — render по языку** (пул из 5 локальных dense/MoE vs топ-3 облака deepseek/kimi/gemini):
| Группа | zh | ja | en |
|---|---|---|---|
| **локаль (пул)** | **0.26** | 0.53 | 0.82 |
| облако-топ | 0.75 | 0.98 | 1.00 |
Recall по языку у всех ~0.951.0 (спот не зависит от языка).
## Выводы (верифицированные)
1. **СПОТ сущностей — решённая задача для ВСЕХ, локаль включительно** (recall 0.951.0 на zh/ja/en). Кандидат-споттинг write-path можно гнать на дешёвой локальной 8b. Даже 0 галлюцинаций (кроме ruadapt).
2. **РЕНДЕР канонического RU — вот где разрыв, и он с крутым ЯЗЫКОВЫМ градиентом у локали:** en 0.82 (западные имена локаль транскрибирует нормально — Джон Картер/Конан), ja 0.53 (средне), **zh 0.26 (локаль проваливается)**. Облако-топ сильно везде (zh 0.75, ja 0.98, en 1.0).
3. **Провалы локали на zh — это прямая нонконформность стандарту Палладия** (реестр **B6**, эмпирически подтверждён): 阿Q→«Ах-Чу», 赵太爷→«Тяо Тай-Я», 祥林嫂→«Сяньлинсяо», 送灶→«Сув-цзя», 祝福→«Бэ-цзю», 羅生門→«Ро-сёмон», 朱雀大路→«Чжу-сюкэ-дайро» — фонетический мусор вместо Палладий-канона («А-кью», «Чжао»). Локаль не знает системы транскрипции zh→ru; это не «плохой перевод», а систематически неверная по стандарту транслитерация.
4. **Бо́льшая локаль НЕ помогает:** 30b-a3b render 0.55 ≈ 8b (0.480.55), но в 34× медленнее (13.5с vs 35с) и recall даже ниже (0.91). Для спота брать дешёвую 8b, не 30b.
5. **deepseek: thinking ПОМОГАЕТ рендеру** (0.85 с thinking vs 0.58 без) — reasoning вытаскивает канон реалий (согласуется с exp03). Но thinking-off deepseek на экстракции **здоров** (12/12, echo бьёт перевод, не JSON-вывод) — просто рендерит хуже (≈уровень локали).
6. **Лучший рендер-value — gemini-2.5-flash** (render 0.92 за 1.4с); kimi лучший по качеству (0.96), но 38с/дорого; deepseek-think 0.85/8.9с. grok/glm/gpt-5-mini слабее по рендеру (0.670.69).
7. **ruadapt-qwen3 — ненадёжен** (5/12 health, единственный с галлюцинациями) — как и предупреждал exp03 «понимание разрушено ru-адаптацией».
## Следствие для дизайна (write-path, уточняет Р4/G1)
Экстракцию разбить на две подзадачи, и разбивка **язык-зависима**:
- **(а) СПОТ кандидатов-спанов — локальная 8b** (recall ~0.98 на всех языках, дёшево/быстро, 0 галлюцинаций). Это дешёвый пре-пасс NER.
- **(б) РЕНДЕР dst — зависит от языка источника:** для **zh — обязательно облако/человек + детерминированная таблица Палладия** (локаль даёт мусор 0.26; даже облако лишь 0.75 — часть zh→ru реалий не имеет единого канона, нужен словарь B6); для **ja — облако** (локаль 0.53); для **en/западных имён — локаль потянет** (0.82), облако для надёжности. Рендер-модель по value — gemini-2.5-flash.
- Промоушен `auto→approved`с человеком/судьёй (G1), особенно на zh, где даже сильная модель не гарантирует Палладий.
## Ограничения
12 кейсов (умеренно, не сотни), 1 прогон на ячейку (temp низкая), gold-render = мой набор accept-регэкспов канона (для спорных реалий — 送灶/洛中 — канон нестрогий, render занижен честно). Render — объективно более трудная для авто-оценки ось, чем recall; человеческая сверка на выборке усилит. Но языковой град**иент (zh≪ja≪en у локали) устойчив и с этим N.
Провенанс: `eval/extract_bench.py` (переиспользует `refusal_bench.call_provider` + `providers.json`), `results.json` с per-кейс `records`. Реальные PD-тексты `eval/data/samples`.