Перейти к содержанию

1 мая 2026 — большой сдвиг архитектуры

За один день закрыли работу которая планировалась на 5-7 дней. Ключевое изменение — переход от promt-базированной phantom-защиты к SQL-deterministic retrieval. Фантомы на конкретные НПА теперь невозможны по архитектуре, а не по промпту.

Что сделано

1. Миграция Lyumi на AX41

  • Новый сервер Hetzner AX41-NVMe (16 vCPU, 64 GB RAM, NVMe SSD), Helsinki, IP 65.108.5.40
  • CPX52 (16 vCPU/32GB) остаётся warm fallback до 5 мая, потом отключим
  • Manual-embed режим в retriever.py: SentenceTransformer + vanilla BAAI/bge-m3, single-path
  • bge-m3-hse-v2 fine-tuned НЕ взяли в прод (trade-off 79% golden(14) / 39% natural)
  • Pushkin (digest bot) также переехал на AX41

2. SQL lookup deployed (главное)

Новый слой retrieval до векторного поиска. lookup_npa.py + lyumi_npa.db в bot.py перед retriever.

База SQL (122 MB): | Таблица | Записей | |---|---| | codes | 8 (ТК, УК, КоАП, ЭК, ЗК, ВК, КЗ, КН) | | articles | 3,114 | | article_parts | 10,709 | | orders | 176 | | international_standards | 217 | | npa_values | 7,643 | | Итого SQL records | ~14,200 |

3. ACGIH TLV-2022 OCR хак

Документ защищён custom CID-шрифтом без ToUnicode mapping. Решение: render через pymupdf 200dpi → rotate -90° → tesseract --psm 4 → split blob по pattern [CAS-num].

Результат: - 616 веществ из 55 страниц «Adopted Values» - 96% с TLV-TWA, 100% с CAS - ~10 минут на OCR всех страниц

lookup_pdk cross-language: - RU↔EN маппинг: бензол↔benzene, сероводород↔hydrogensulfide, аммиак↔ammonia, etc. - Запрос «TLV бензол» → КР ПДК + ACGIH (Benzene 0.05/2.5 ppm A1) в одном LookupHit

Инсайты

Cluj insight: архитектура выше промпта

«Мы делали ошибку, мы промптами пытались архитектурные дыры заткнуть» — Камал

Bonus insights

  • bge-m3 ST/FE dense идентичны (cosine 1.000000 на 5 запросах) — sparse можно подключать без переиндексации
  • Whisper Groq бесплатно — voice INPUT в проде
  • Cohere rerank вредит B_code_article -11pp — BM25 находит точный результат сразу, реранкер перетасовывает и теряет. Идея: adaptive rerank для запросов по регексу кодекса. Но в проде SQL уже забирает эту категорию.

Бенчмарки

Retrieval baseline (vanilla bge-m3 + BM25 + Cohere rerank, golden_v1 90q, semantic match)

Final numbers (с полным rerank): | Метрика | Значение | |---|---| | Avg keyword match @top-10 | 56.5% | | Hit@10 (≥50% kw) | 61.1% | | Strong Hit@10 (≥80% kw) | 32.2% | | Zero-hit | 0% | | Speed | 7.6s/query (с sleep 7s для Cohere Trial 10 RPM) |

По категориям (Hit@10): | Категория | n | Hit@10 | kw@10 | Комментарий | |---|---|---|---|---| | A_direct_number | 26 | 88.5% | 78.1% | НПА с номером — потолок | | B_code_article | 18 | 27.8% | 30.7% | Статьи кодекса — SQL решает в проде | | C_topic | 13 | 53.8% | 52.6% | Тематические | | D_mixed | 13 | 76.9% | 68.7% | Смешанные | | E_edge | 15 | 53.3% | 44.9% | Edge cases | | F_date_ministry | 5 | 40.0% | 49.3% | Дата/министерство |

SQL coverage (smoke test после деплоя)

  • ст.156 ТК РК, Приказ ҚР ДСМ-70, ПДК сероводорода/аммиака/бензола/свинца/ртути, TLV benzene/ammonia/formaldehyde/H₂S — все ✅
  • Боевой скрин от юзера: Раздел 4 ТК РК → Люми точно назвала ст.179-190 + «документ у меня в базе целиком»

ACGIH OCR

  • 616 веществ, 96% с TLV-TWA, 100% с CAS

Decisions и deferrals

Решение Статус
Sparse retrieval (bge-m3) Дефер на 9 мая — после недели логов, сравнение с baseline 61.1% Hit@10
Multi-vector (ColBERT) НЕ делаем — 334 GB storage, не влезет в RAM AX41
ONNX-квантизация беквыход в testing не дал speedup — deferred
Compliance Calendar НЕ делаем — много возни
Investigation Module Спека в lyumi/modules/investigation, sprint позже
Document Intelligence Спека в lyumi/modules/document_intelligence, sprint позже
Voice Output НЕ делаем, Voice INPUT уже в проде
Adaptive rerank (skip Cohere на B_code) Отложено — SQL уже решает

План на следующую неделю

2-8 мая: - Наблюдаем прод с SQL — выявляем где lookup_npa ломается, false negatives - 5 мая: выключаем CPX52 - По фидбэку юзеров: фиксы SQL detection regex'ов

9 мая (суббота): - Решение по sparse retrieval по числам log_analysis.py + eval +sparse vs baseline - Критерий: +3pp Hit@10 на golden_v1 → деплой, меньше → остаёмся на baseline

Цифры дня

  • 14,200 SQL records в проде
  • 616 веществ ACGIH (96% с TWA)
  • 167,332 чанков ChromaDB
  • Hit@10 baseline = 61.1%, Strong = 32.2%, kw = 56.5%
  • 5-7 дней планировали → 1 день сделали
  • 0 downtime