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

Lyumi v4 — Structured retrieval (SQL lookup)

1 мая 2026, вечер. Архитектурный shift v3 → v4 — переход от prompt-patches к structured retrieval. Sprint завершён за один день (изначальная оценка была 5-7 дней; Камал поправил эстимат, оказался прав).

Suть сдвига

v3 (RAG-based): 164K чанков в ChromaDB → embedding retrieval → top-5 → LLM сшивает → промпт-патчи (anti-phantom 3 линии, fact-anchors, citation verifier, blacklist фантомных приказов) ограждают от галлюцинаций.

v4 (Hybrid structured + semantic): 14,216 records в SQLite + 164K чанков в ChromaDB. Для запросов с явными identifiers (ст. N кодекса, Приказ N, OSHA 1910.X) — детерминированный SQL lookup ПЕРЕД semantic. LLM получает structured data + опц. semantic дополнение.

Ключевое отличие: на запросах с явными identifiers phantom НПА-факта impossible by design. Не нужно надеяться что embedding найдёт правильный chunk — SQL exact match гарантирует точный текст.

Что в проде сейчас (1 мая 2026)

SQL база /opt/lyumi/lyumi_npa.db (118 MB, mounted в Docker как /app/lyumi_npa.db)

14,216 структурированных records:

Категория Количество Источник
Articles (статьи кодексов) 3,114 8 кодексов РК
Article parts (пункты внутри) 10,709 regex ^\s+(\d+(?:-\d+)?)\.
Orders (приказы/законы/ТР) 176 v/p/z/h PDF
International standards 217 OSHA, ISO, IOGP, NFPA, ANSI, ACGIH, AIHA, NIOSH, ILO, NEBOSH, OHSAS, IPIECA, SBTi

8 кодексов РК (полная иерархия Раздел/Глава/Статья/Пункт)

Code Articles Закон
КоАП 1,071 № 235-V от 2014
УК 503 № 226-V от 2014
ЭК 418 № 400-VI от 2021
КЗ 297 № 360-VI от 2020
КН 284 № 125-VI от 2017
ТК 221 № 414-V от 2015
ЗК 186 № 442 от 2003
ВК 134 № 178-VIII от 2025

176 orders

  • 139 приказы (МТСЗН 7+, МЧС 25, МЗ 15, МЭГПР 10, Минэнерго 10, МВД 7, прочие)
  • 8 ТР ТС/ЕАЭС
  • 5 постановлений Правительства
  • 3 закона
  • 21 не определилось (часть методичек с cyrillic именами, старые приказы)

217 international standards

OSHA 70, NFPA 7, AIHA 4, IOGP 3, ANSI 3, ACGIH 2, API 2, ILO 2, SBTi 2, NIOSH 1, org="?" 121 (parser detection не сработал — будет дочистка через Sonnet metadata extraction в monthly cycle).

Архитектура retrieval pipeline

User query
    ↓
[Synonym expansion + Multi-query async + Cohere Rerank] (как в v3)
    ↓
[Registry hint] из document_registry (если запрос про конкретный документ)
    ↓
[NEW v4] NPA SQL lookup — npa_lookup(query):
    ├── ст. N <кодекс>          → article exact match
    ├── Приказ N (МТСЗН/МЧС/МЗ)   → order exact match
    └── OSHA 1910.X / ISO N / IOGP N → international standard lookup
    ↓
hits_to_context() injects [ТОЧНЫЕ ДАННЫЕ ИЗ БАЗЫ НПА] блок ПЕРЕД semantic chunks
    ↓
LLM (Sonnet 4) получает structured data + опц. semantic дополнение
    ↓
Streaming Telegram ответ
    ↓
Reflection layer (clean на структурированных запросах)

Smoke test 1 мая 19:51 (4/4 pass)

Запрос SQL hit Время Что пишет бот
ст. 156 УК РК 57s cold Точные части 1-4: 160 МРП → 200 МРП → 5 лет → 7 лет + причинно-следственная связь
Приказ 344 МТСЗН наряд-допуск 10s Реальные детали: 2 экземпляра, ЛЭП/газопроводы, хранение 1 год / при НС с расследованием
ст. 11 ТК РК 7s "Акты работодателя" + ЭЦП + связка с СУОТ через ст. 182
Приказ 340 МТСЗН СУОТ 10s Структура: Планирование/Функционирование/Контроль/Совершенствование

Reflection: clean после каждого — нет галлюцинаций, нет редактирования.

Тонкие места (что v4 НЕ решает)

1. Phantom examples / phantom statistics

SQL устраняет phantom НПА-факта (точный текст статьи). Но если юзер просит "приведи пример из практики казахстанского предприятия" — LLM может выдумать пример, потому что в SQL этого нет.

Что остаётся: Reflection layer + strict prompt rules для не-цитатной части ответа. Anti-phantom 3 линии частично нужны для examples / cases.

2. Тематические запросы

"Как ст. 156 УК применяется при коллективных переговорах в нефтегазе" — это не lookup-запрос, это semantic. ChromaDB остаётся primary source для тематических. Это норма — гибрид.

3. Иерархия правил/положений в orders

parse_orders.py извлёк metadata (number, issuer, date, title) + full_text для 176 файлов. Иерархия секций внутри (Глава I → 1. → 1.1) НЕ extracted — это в TODO для дочистки.

Это значит: "Приказ 344 МТСЗН пункт 5.3" найдёт приказ, но не пункт 5.3 точечно. Полный текст уйдёт в LLM, она найдёт.

4. International standards с org="?" (121 файл)

Parser detection не сработал на сложных filenames. OSHA 1910.146 ищется по filename pattern — но не все стандарты имеют чистое имя. Нужна Sonnet metadata extraction (~$0.50 на 121 файл).

Промпт-патчи: что МОЖНО снимать в next sprint

После v4 deploy эти compensations стали избыточны для structured queries. Не трогать прямо сейчас (бот в проде стабилен), но в отдельный prompt audit sprint удалить:

Промпт-патч Где Что заменяет
### ⛔ BLACKLIST фантомных приказов (ҚР ДСМ-16 и т.д.) llm.py SQL не содержит несуществующих документов
Anti-фантом Линия 1 (Writer rule про темы приказов) llm.py system prompt SQL даёт реальную тему
Anti-фантом Линия 2 (Reflection #10 phantom attribution) reflection.py Может остаться для examples; для НПА упрощается
Anti-фантом Линия 3 (Pre-flight kb_api Haiku verify) bot.py Замещается детерминистическим lookup
Fact-anchors 1.3м / 15 м/с / 7 лет / 188-V llm.py Все эти факты теперь в SQL по lookup
Citation verifier (regex post-check ссылок на НПА) bot.py verify_citations SQL exact match до запроса к LLM
Synonym expansion для structured queries llm.py expand_query Не нужен (regex parsing query сам понимает "ст. N" / "Приказ N")

Что ОСТАЁТСЯ в промптах (реально семантические правила): - Тон Люми (профессиональный, женский род о себе) - Юрисдикция РК (запрет на РФ-нормы — но это уже в данных через cleanup) - Формат документов (TBT/JSA/PTW pipelines имеют свою логику) - Anti-phantom для examples / statistics — там где SQL не помогает

Ожидаемое сокращение system prompt: −30-50% размера, без потери качества (часто с улучшением — модель не путается в собственных правилах).

Maintenance cycle (ежемесячный)

Кодексы и приказы РК обновляются. Каждый месяц:

  1. Скачать новые редакции с Әділет → Карточки Core New/local standards/ на маке
  2. Запустить парсеры локально: bash cd hse_copilot/npa_parser python3 parse_kodex.py --all --db /tmp/lyumi_npa.db python3 parse_orders.py --all --db /tmp/lyumi_npa.db python3 parse_international.py --db /tmp/lyumi_npa.db
  3. cp /tmp/lyumi_npa.db в Карточки Core New/hse_copilot/lyumi_npa.db (iCloud)
  4. scp на AX41: bash scp ~/Library/.../hse_copilot/lyumi_npa.db root@65.108.5.40:/opt/lyumi/
  5. Restart: bash ssh root@65.108.5.40 "docker compose -f /opt/lyumi/docker-compose.yml restart bot"
  6. Smoke test ключевых запросов (ст. 156 УК, Приказ 344, новых добавленных)

Полный цикл = ~10-15 минут активной работы. Re-parse быстрый (5 минут), scp быстрый, restart быстрый.

Файлы

На маке Карточки Core New/hse_copilot/

  • npa_parser/parse_kodex.py — парсер 8 кодексов (regex Раздел/Глава/Статья/Пункт)
  • npa_parser/parse_orders.py — парсер приказов/законов/ТР (multi-pattern для header)
  • npa_parser/parse_international.py — парсер 226 international standards
  • lookup_npa.py — детерминистический SQL lookup с regex parsing query
  • lyumi_npa.db (118 MB) — production copy SQLite
  • bot.py — hook NPA SQL lookup перед registry_hint

На AX41 /opt/lyumi/

  • lyumi_npa.db (mounted в Docker как /app/lyumi_npa.db)
  • lookup_npa.py (COPY *.py в Dockerfile)
  • bot.py с hook'ом
  • .env дополнен LYUMI_NPA_DB=/app/lyumi_npa.db
  • docker-compose.yml дополнен volume mount

Что в очереди (не блокирующе)

  1. Дочистить 121 international с org="?" через Sonnet metadata extraction (~$0.50, 30 минут)
  2. Иерархия секций в orders — extract Глава/Раздел/Пункт для приказов и правил (1-2 часа на edge cases)
  3. 21 "?" doc_type в orders — методички с cyrillic именами, старые приказы
  4. 67 orders с пустым issuer — расширить ISSUER_KEYWORDS
  5. Prompt audit — снять промпт-патчи перечисленные выше (отдельный sprint, 1-2 часа)
  6. Tool calling rewrite — явный choice LLM между lookup_tool / semantic_search / web_search (Q3 в strategy_2026)

Lessons (записаны в memory как feedback_*)

  1. AI-assisted dev радикально быстрее human-time эстиматов. "5-7 дней sprint" → 30 минут активного кода + ~2 часа integration. Камал поправил эстимат, был прав.
  2. Architecture > prompts. Один SQL lookup убирает 5+ промпт-компенсаций. OpenEvidence + GPT-5.5 "гоблины" — индустрия пришла к тому же.
  3. Production data парсится через regex на 90%+ на стандартных форматах Әділет. LLM нужен только для edge cases.
  4. iCloud + SQLite = "disk I/O error" — SQLite требует local filesystem. SQL DB положили в /tmp/ и потом cp в Карточки.

Связи

  • [[lyumi/migration_ax41]] — миграция инфры (1 мая утро)
  • [[lyumi/finetune_apr30]] — fine-tune эксперимент 30 апр (на полку, отдельная история)
  • [[lyumi/strategy_2026]] — общая стратегия года
  • project_v4_sql_lookup_deployed.md — memory snapshot 1 мая
  • project_monthly_lora_loop.md — стратегия LoRA (отдельный трек)
  • feedback_no_hybrid_architectures.md — single-path принцип Камала