Skip to content

Latest commit

 

History

39 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

[Русский] · English

HEFEST

Химическая безопасность завода. Офлайн, с провенансом, без выдуманных цифр

Поиск по паспортам здесь фундамент. Продукт стоит на нём — двенадцать рабочих экранов: что надеть, можно ли ставить рядом, куда не пускать людей, какой класс отхода, что делать, когда замер ушёл за ПДК.

tests license: MIT Python 3.10+ on-prem

Реакция на превышение: кратность ПДК считается только при совпадении единиц

Мастер смены вводит замер. 3 мг/м³ — система считает кратность. 15 ppm — отказывается считать и говорит почему: единицы разные, а пересчёт ppm в мг/м³ здесь запрещён.

HEFEST (Гефест — бог-кузнец): из хаоса PDF-паспортов система кует проверяемую карточку вещества. Отвечает по паспорту, при сомнении молчит, подпись — за человеком. Рабочее имя репозитория — rag-sds.

Warning

Это инструмент поддержки решений, а не паспорт безопасности. Цена ошибки здесь — здоровье человека. Перед любым применением за пределами демонстрации прочитайте DISCLAIMER.md и LIMITATIONS.md.

Это не поиск по документам

Спросить словами — это вход. Дальше ответ надо превратить в действие, иначе смене от него толку нет. Поверх поиска стоит прикладной слой: у каждого инструмента своя расчётная логика, а не пересказ найденного текста.

Инструмент Вопрос смены Что за ним стоит
Аварийная карточка Разлив хлора — что делать? ООН/ДОПОГ, IDLH, зоны изоляции и эвакуации ERG‑2024, первая помощь, QR на тару
Зона заражения АХОВ Куда не пускать людей? Расчёт по РД 52.04.253‑90; 11 АХОВ с верифицированными коэффициентами, вне перечня — отказ
Карта склада Можно ли ставить рядом? Матрица совместимости по сегрегационным группам + Раздел 10 паспортов, авто‑аудит опасных пар
Подбор СИЗ Что надеть? Класс опасности, агрегатное состояние и химическая группа → перчатки, органы дыхания, кожа
Реакция на превышение Замер 3 мг/м³ — это много? Кратность ПДК, только при совпадении единиц; иначе честный отказ
Класс отхода Куда это списывать? Предварительная оценка по ФККО; без показателей класс не присваивается
Карточка диспетчера Кого оповещать? Оперативная выжимка по веществу для дежурной смены
Режим инспектора Что покажут на проверке? Обход площадки глазами проверяющего: провенанс, пробелы, устаревшие ссылки
Этикетка СГС Что клеить на тару? Официальные пиктограммы, сигнальное слово, класс, ПДК, IDLH, QR на карточку

Поиск и ответ — это console.html, один экран из восемнадцати. Остальные семнадцать работают с той же базой, но отвечают на вопросы, которые задают не поиску, а инженеру.

Чем этот проект отличается

Обычная RAG-система, столкнувшись с пробелом в данных, выдаёт правдоподобный текст. В промышленной безопасности это недопустимо, поэтому здесь всё построено вокруг одного правила: нормативка не выдумывается. На практике это означает четыре наблюдаемых свойства:

Свойство Как проверить
Молчит, когда нет оснований. Вопрос вне базы получает честный отказ, а не сочинённый ответ. POST /ask с посторонним вопросом → "abstained": true, "sources": []
Не пересчитывает единицы. ppm не превращается в мг/м³: кратность ПДК считается только при совпадении единиц, иначе «сверьте вручную». GET /shift/хлор?value=15&unit=ppm"pdk_ratio": null
Не выдаёт типовое за паспортное. Значение по химической группе помечено baseline и несёт дисклеймер. GET /qualitydata_grade: {passport: 52, baseline: 2545}
Показывает пропуски, а не заполняет их. Нет данных — так и написано; класс отхода без показателей не присваивается. POST /waste/estimate"class": null, "confidence": "insufficient_data"

Каждое из этих свойств закреплено тестом: make test (113 тестов, офлайн, без Ollama и сети).

Быстрый старт

git clone https://github.com/ilyautov/hefest.git && cd hefest
python3 -m pip install -r requirements/dev.txt
make run          # сервис на http://127.0.0.1:8012

Лексический режим работает из коробки: без Ollama, без ключей, без сети и без выкачивания эмбеддингов из Git LFS. Проверка: curl -s localhost:8012/health. Интерфейс — откройте home.html в браузере и укажите адрес сервиса.

Семантический режим (заметно выше качество, нужен локальный Ollama):

ollama pull bge-m3 && ollama pull qwen2.5:7b
make run-semantic

Если эмбеддингов нет, сервис честно откатывается на лексику, а не падает. Пересобрать индекс из корпуса: bash rebuild_index.sh. Подробности клонирования — КЛОН.md.

Что внутри

  • 2597 веществ с регуляторными значениями РФ: ПДК из ГН 2.2.5.3532-18 / СанПиН 1.2.3685-21, класс опасности по ГОСТ 12.1.007-76, GHS, хранение, СИЗ, первая помощь.
  • 25 970 разделов-чанков по структуре ГОСТ 30333-2022 (16 разделов паспорта).
  • Работа по площадке — карточка предприятия, реестр химикатов, карта склада, режим инспектора, скоуп поиска. Работает на вашем реестре: сведений о юридических лицах публичная поставка не содержит (см. DATA-LICENSE.md, раздел 4).
  • 6 инструментов для завода: подбор СИЗ, карта склада, режим инспектора, предварительный класс отхода, оперативная карточка диспетчера, реакция на превышение для мастера смены.
  • 43 эндпоинта FastAPI и 18 HTML-экранов без сборки.

Реестр предприятий в поставку не входит принципиально: перечень обращающихся веществ — это утверждение о промышленной безопасности организации, и проект его не делает. Свой реестр подключается за одну команду, схема — в data/plants.example.json.

Полнота базы честная и невысокая: паспортная градация — 52 вещества, остальное типовое по группе, 2546 записей ждут подписи эксперта. Это видно в GET /quality и разобрано в LIMITATIONS.md. Система в поставке знает мало и прямо об этом говорит.

Как это выглядит

Две сцены, и это не один резиновый макет, растянутый между ними. Цех — телефон в руке, перчатки, счёт на секунды. Кабинет — монитор, плотность, провенанс, возможность докопаться до источника.

Аварийная карточка хлора: номер ООН, знаки ДОПОГ, IDLH, зоны изоляции и эвакуации, первая помощь
Аварийная карточка. Хлор: ООН 1017, IDLH, зоны ERG‑2024, первая помощь, СИЗ. Внизу QR — навести с тары.
Карта склада: вещества по зонам хранения с подсветкой несовместимых пар
Карта склада. Что где стоит и какие пары нельзя ставить рядом — сегрегационные группы плюс Раздел 10.
Подбор средств индивидуальной защиты по веществу
Подбор СИЗ. Что надеть под конкретное вещество — с пометкой, паспортное это указание или типовое по группе.
Оперативная карточка диспетчера
Карточка диспетчера. Выжимка для дежурной смены: что произошло, кого оповещать, что сказать.

Скриншоты сняты на обезличенном реестре площадок из поставки — названия организаций в публичной версии отсутствуют по построению.

Документация

Документ О чём
DISCLAIMER.md Границы применения. Читать до эксплуатации
LIMITATIONS.md Где система слаба — 12 честных пунктов
DATA-LICENSE.md Происхождение и права на каждый набор данных
CONTRIBUTING.md Как участвовать; святое правило проекта
SECURITY.md Что здесь считается уязвимостью (обход контура честности — тоже)
docs/АРХИТЕКТУРА.md Схемы и потоки данных
docs/О-СИСТЕМЕ.md Объяснение для заказчика без терминов
docs/ВНЕДРЕНИЕ-дорожная-карта.md Путь до производственного контура
DEMO.md · docs/ДЕМО-СЦЕНАРИЙ.md Сценарии показа по ролям

Архитектура

данные (substances + plants, реальные открытые источники)
   -> corpus.py        : генерация SDS-документов по ГОСТ 30333 + линковка заводов
   -> retriever.py     : гибрид char+word TF-IDF + BM25 + сущностный буст + интент раздела + scope завода
   -> backends.py      : сменные адаптеры эмбеддингов и генерации (вендор-нейтральность)
   -> cache.py         : semantic cache (L2 exact + L3 semantic, исключение параметрических)
   -> service.py       : FastAPI (/search /ask /plant /substance /emergency /compat /ghs /zone /quality /audit /registry /quiz /qr /card /export /sanpin /erg /pubchem /verify /verification /review /reviews /gost/summary /normative /compliance/selfcheck) + Dockerfile
   -> verification.py  : слой ЭКСПЕРТНОЙ подписи ДАННЫХ вещества (verified/needs_review/rejected, кто/когда) — отдельно от машинной confidence
   -> answer_review.py : слой оценки ВЫДАЧИ (сверка ответа с первичкой: retrieval/extraction верны? полезно?), подписанные оценки
   -> physchem.py / sanpin_env.py / transport.py : обогащение по CAS — физхимия (PubChem), ПДК атмосферы/воды (СанПиН), номер ООН/класс груза (PubChem/DOT)
   -> normative.py / gost_sections.py / audit_versions.py : реестр нормативки (версии/статус), карта 16 разделов ГОСТ 30333 (gost_map в /substance, дашборд /gost/summary), аудит устаревших ссылок
   -> eval_abstention.py: eval ОТКАЗА (safety-метрика): покрытие/корректный отказ/галлюцинации; порог калибруется
   -> compat.py        : матрица совместимости хранения (сегрегация несовместимых, NFPA/CSB + Раздел 10)
   -> ghs_map.py       : GHS-слой (9 пиктограмм СГС + сигнальное слово из меток паспорта)
   -> rd_zone.py       : расчёт зоны заражения АХОВ по РД 52.04.253-90 (коэф. верифицированы по 3 копиям)
   -> hygiene.py       : аудит-лог запросов + состояние паспорта + дэшборд качества данных
   -> registry.py      : реестр химикатов по заводам + авто-аудит несовместимости хранения (попарно)
   -> quiz.py          : детерминированный обучающий квиз (без LLM, ответы из паспорта)
   -> sanpin.py        : расшифровка особых отметок СанПиН 1.2.3685-21 (О/К/А/Ф/кожа), строгий парсер
   -> pubchem.py       : H-коды СГС (ГОСТ 31340) + сверка наших знаков с эталоном PubChem
   -> fetch_idlh.py    : загрузка острого порога IDLH из NIOSH по CAS (public domain) -> data/idlh.json
   -> fetch_synonyms.py: русские синонимы из Wikidata (CC0) по CAS -> data/synonyms.json (recall поиска)
   -> fetch_pubchem.py : эталонная GHS-классификация PubChem (NIH) по CAS -> data/pubchem_ghs.json
   -> generate_ui.py   : сборка самодостаточного офлайн-UI (index_pro.html, генерируется)
   -> substance.html   : единая карточка вещества — все слои на одном экране (центр. точка входа)
   -> console.html     : живой поиск/ответ к семантическому сервису
   -> emergency.html   : аварийные карточки (АХОВ: ООН/ДОПОГ + IDLH + отметки СанПиН + зона ERG + QR)
   -> safety.html      : операции/хранение (совместимость · GHS · зона АХОВ · гигиена базы)
   -> registry.html    : реестр по заводам (вещества + опасные пары + выгрузка CSV)
   -> label.html       : печатная этикетка СГС (офиц. пиктограммы + класс + ПДК + IDLH + QR-код)
   -> quiz.html        : инструктаж/проверка знаний по веществу
   -> guide.html       : инструкция с примерами «ввод → результат»
   -> assets/ghs/*.svg : официальные пиктограммы СГС (UNECE/Wikimedia, public domain)
ollama-mcp/server.py   : MCP-мост к локальной Ollama (сознательный доступ агента)

Прикладные слои химбезопасности (лучшие практики отрасли):

  • Совместимость хранения (/compat) — «можно ли хранить X рядом с Y»; вердикт по сегрегационным группам + текст Раздела 10 паспортов. (CSB: несовместимое хранение — фактор ~25% химинцидентов.)
  • GHS (/ghs) — пиктограммы СГС + сигнальное слово, выведены из паспорта (H-коды не выдумываем).
  • Зона АХОВ (/zone) — глубина зоны по РД 52.04.253-90; 11 АХОВ с верифицированными коэффициентами, вне перечня РД — честный отказ; needs_review, не замена утверждённого расчёта объекта.
  • Гигиена базы (/quality, /passport, /audit) — полнота критичных полей, статус верификации, аудит-лог. Честная находка: паспортные СИЗ+ПП+хранение лишь у 52 веществ — инструмент показывает, что дозаполнять.
  • Типовое руководство по группе (/guidance, engine/baseline.py) — для 2545 bulk-веществ без паспортных оперативных полей: вычисляемые СИЗ/первая помощь/хранение по химической группе (кислоты/ щёлочи/окислители/токсичные газы/цианиды…) + классу опасности. Поля вещества НЕ фейк-заполняются; руководство помечено типовое по группе (vs паспорт). data_grade: passport / partial / baseline. 100% веществ получают actionable-руководство, но типовое НЕ маскируется под паспортное.
  • Реестр по площадкам (/registry, engine/registry.py) — для каждой площадки вашего реестра список веществ и авто-аудит опасных пар для совместного хранения (попарно через compat). Количество/место/ ответственного предприятие заполняет само (не синтезируем). Выгрузка в CSV (/export/registry.csv, BOM + ; для Excel/1С).
  • Этикетки СГС + QR (/qr, /card, label.html) — печатная этикетка для тары (знаки опасности, класс, ПДК, хранение) с QR-кодом (segno, чистый python, SVG), ведущим на мобильную карточку первой помощи /card. QR также встроен в аварийную карточку. Наведи телефон у ёмкости — видишь, что делать.
  • Обучающий квиз (/quiz, engine/quiz.py) — инструктаж по веществу для персонала, детерминирован из паспорта без LLM (в безопасность-обучении галлюцинации недопустимы): класс/ПДК с отвлекающими + открытые вопросы по СИЗ/ПП/хранению с пометкой источника.

Обогащение из открытых данных мира и РФ (всё с провенансом, needs_review, без выдумывания):

  • IDLH — острый порог (/substance, /emergency, engine/fetch_idlh.py) — концентрация «немедленно опасно для жизни» (без СИЗ гибель за ~30 мин). Тянется НАПРЯМУЮ из NIOSH (cdc.gov/niosh/idlh, public domain) по CAS. Дополняет хронический ПДК острым порогом для аварийного реагирования. 28 веществ (хлор 10 ppm, фосген 2 ppm, аммиак 300 ppm…); NIOSH покрывает ~500 веществ, для остальных честно пусто.
  • Русские синонимы (engine/fetch_synonyms.py, data/synonyms.json) — из Wikidata (CC0) по CAS. Чинит recall: «оксиран/окись этилена/этиленоксид» → одно вещество. Резолвинг по синониму встроен в lookup-эндпоинты и автодополнение. Покрытие — распространённые вещества (которые реально ищут); не все 2597 (Wikidata знает ~274 наших CAS). Без генерации — только из источника.
  • Особые отметки СанПиН 1.2.3685-21 (/sanpin, engine/sanpin.py) — расшифровка кодов О (остронаправленного действия — нужен непрерывный контроль воздуха), К (канцероген), А (аллерген), Ф (фиброгенная пыль), + (защита кожи). Эти отметки уже в базе из ингеста ГН/СанПиН — слой их раскрывает. Строгий парсер: декодирует только чистые коды, свободный текст игнорирует (иначе буквы из слов → ложный «канцероген»).
  • ERG-2024 + ООН/ДОПОГ (/erg, data/erg_ahov.json) — расстояния изоляции и эвакуации (US DOT/Transport Canada, public domain, через CAMEO; верифицировано по 3 источникам) для 7 АХОВ. Ориентир ПЕРВОГО реагирования — не заменяет расчёт зоны по РД 52.04.253-90. Закрыл пробел: хлор теперь распознаётся как АХОВ (ООН 1017).
  • Официальные пиктограммы СГС (assets/ghs/*.svg, UNECE/Wikimedia, public domain) — на этикетке и карточке вещества, с graceful-fallback на рисованные при отсутствии файла.
  • Эталонная GHS из PubChem (/ghs, /pubchem, engine/pubchem.py) — авторитетные пиктограммы + H-коды (расшифрованы по ГОСТ 31340-2013) из PubChem (NIH, public domain, агрегат ECHA/NITE) по CAS. Сверка: где наша выведенная из паспорта классификация недо-/пере-указывает знаки относительно эталона — флаг аудитору (напр. для хлора PubChem дополнительно даёт GHS05/GHS08). H-коды показываются в карточке вещества.

Доверие = отказ + экспертная подпись (/ask, /verify, /verification, engine/verification.py, engine/eval_abstention.py) — два механизма, обязательных для safety-критичного прода. Отказ: если релевантность ниже порога ABSTAIN_THRESHOLD (дефолт 0.62, калибруется на eval завода), система не генерирует, а честно отправляет к паспорту — на eval-наборе 100% покрытия реальных вопросов при 0% галлюцинаций на вопросах вне базы. Экспертная подпись: статус verified/needs_review/rejected с фиксацией «кто/когда» — отдельно от машинной confidence; по умолчанию всё needs_review (система сама ничего не «подтверждает»). Значок в карточке + дисклеймер «поддержка принятия решений, первоисточник — паспорт». Путь внедрения — docs/ВНЕДРЕНИЕ-дорожная-карта.md.

Сверка выдачи с первичкой (/review, /reviews, engine/answer_review.py, console.html, reviews.html) — третий слой доверия: под каждым ответом человек видит ТОЧНЫЙ текст найденного раздела паспорта (первичку) и подписанной оценкой фиксирует, верно ли система достала раздел (retrieval) и собрала ответ (extraction), и полезно ли. Дашборд качества разделяет retrieval- и extraction-ошибки. Принцип: ответ — удобство, паспорт — истина; и копится размеченный лог для калибровки порога/эвала.

Обогащение по CAS (physchem.py, sanpin_env.py, transport.py) — ядро из юридически чистых источников: public domain (PubChem/NIH, NIOSH) и официальные акты РФ (СанПиН 1.2.3685-21, ст. 1259 п.6 ГК — не охраняется): ПДК атмосферы населённых мест и воды (ОТДЕЛЬНО от ПДК рабочей зоны), GHS, номер ООН/класс груза. Слой физ-химии (темп. вспышки, НКПР/ВКПР, давление пара, растворимость) идёт через агрегат PubChem, который цитирует и справочники с ограничительной лицензией (ICSC ILO/WHO и др.) — на некоммерческом пилоте показываем их с провенансом и needs_review, описания локализованы (physchem_l10n.py, числа/единицы без пересчёта), на проде слой замещается паспортами завода. IARC не используется. Всё с провенансом и needs_review.

Соответствие ГОСТ 30333 и ФЗ (normative.py, gost_sections.py, audit_versions.py, gost.html, docs/СООТВЕТСТВИЕ-ГОСТ-ФЗ.md) — выдача выстроена по 16 разделам ГОСТ 30333-2022 (заменил 30333-2007): в каждом /substance поле gost_map показывает, чем закрыт раздел (свой слой / частично / корпус / пробел) с провенансом; дашборд /gost/summary — покрытие по всей базе. Реестр нормативки (/normative) с версией и статусом каждого акта + аудит устаревших ссылок. ФЗ-контур (/compliance/selfcheck): офлайн-рантайм, X-API-Key, append-only аудит-лог, легальность источников — снимок под 152/187/116-ФЗ. Раздел 13 «удаление отходов» закрыт слоем waste.py (типовые меры по группе + рамка 89-ФЗ/ФККО/Приказ Минприроды № 536; класс отхода I–V и код ФККО — эколог, не выдумываем). Полных структурных пробелов в 16 разделах нет; где данные типовые/корпусные — видно честно. Формулировки названий разделов — на сверке с оригиналом PDF.

Вендор-нейтральность как отстройка. Эмбеддинги и генерация спрятаны за адаптер. Дефолт демо: лексический офлайн (без ключей). Прод on-prem: Ollama на железе завода (bge-m3 эмбеддинги + qwen2.5 генерация), данные не уходят с контура. Опции: OpenRouter (бенчмарк качества), GigaChat (РФ-облако под субсидию РФРИТ). Выбор бэкенда под данные и контур безопасности завода.

Честный eval (воспроизводимо: python3 engine/evaluate.py)

На полной базе (48 веществ, 480 чанков), 25 предметных запросов + 3 плант-скоуп:

Метрика Значение
Вещество top-1 88%
Вещество top-3 100%
Вещество + раздел top-1 84%
Плант-скоуп top-1 100%
Latency (CPU, без GPU) ~3 мс

Масштаб до полной базы ГН (обновление 11.06): через ingest_sanpin.py --html загружена полная таблица ГН 2.2.5.3532-18 (HTML с meganorm, текстовый слой, не скан): 2601 вещество, 26010 чанков. На этом масштабе лексический гибрид честно просел: top-1 60% (было 88%), latency 172 мс (было 3). Причина: на тысячах веществ стеммы-триггеры сталкиваются, char-TF-IDF тяжелеет. Это и есть потолок лексики и прямое обоснование прод-пути: семантические эмбеддинги (Ollama bge-m3) + векторная БД (Qdrant). Архитектура к свопу готова (адаптеры в backends.py). Showcase-UI (генерируется скриптом engine/generate_ui.py) оставлен на 48 verified (88%, мгновенно); полная база живёт в данных и сервисе. Safety: 68 веществ из ингеста с пустым ПДК/классом помечены на ревью в data/substances_sanpin.json, все sanpin-записи = needs_review, наши 48 verified не перетёрты.

Семантическая переиндексация (обновление 13.06, измерено, не прогноз): все 26010 чанков переиндексированы локальной Ollama bge-m3 (1024-мерные эмбеддинги, on-prem, данные не уходят) → data/embeddings.npy. Билд: python3 engine/build_semantic_index.py (батчевый /api/embed). Eval семантического retrieval — python3 engine/semantic_eval.py (голый косинус) и python3 engine/semantic_hybrid_eval.py (косинус + плант-скоуп).

Метрика Лексика @2601 Голый косинус Семантика + плант-скоуп + кросс-энкодер реранк
Вещество top-1 60% 84% 84% 92%
Вещество top-3 84% 96% 96% 92%
Вещество+раздел top-1 52% 64% 64% 68%
Плант-скоуп top-1 33% 100% 100%
Latency (median, вкл. вызов Ollama) 172 мс 181 мс ~210 мс 818 мс

Реранк — bge-reranker-v2-m3 (кросс-энкодер, torch+MPS), конвейер top-N косинусом → реранк → top-k (semantic_rerank_eval.py, RERANK=1 в сервисе). Запасной air-gapped-вариант — LLM-реранк на Ollama (top-1 88%, но ~6 с/запрос). Цепочка масштаба: лексика 60% → семантика 84% → +реранк 92%. Оставшиеся 2 промаха top-1 частью — артефакты HTML-ингеста ГН (см. ниже), а не провал ретрива.

Grounded-генерация (обновление 13.06, измерено): /ask с LLM_BACKEND=ollama собирает ответ на qwen2.5:7b строго по найденным разделам, с цитатами [N] и temperature 0 (детерминированно, safety). Проверено end-to-end: на запрос вне базы («сколько стоит билет на самолёт») retrieval всё равно вернул 3 нерелевантных чанка, но модель честно ответила «в базе нет данных» — grounding-guard держит, галлюцинаций нет. Дефолт демо остаётся extractive (без модели, нулевой риск).

Прогноз README подтвердился: семантика вернула top-1 60% → 84% на полной базе. Честная находка по ходу: голый косинус теряет плант-скоуп (запрос по площадке уезжает в созвучное вещество, 33%) — чинится тем же scope-слоем из retriever.py до 100%, без потери предметного top-1 (scope срабатывает только на плант-запросах). А вот два других лексических слоя — сущностный буст и интент раздела — на 2601 веществе шумят (5-буквенные стеммы коллизируют, +0.12 промотирует правильный раздел не того вещества) и роняют top-1 до 68–80%, поэтому на масштабе они отключены. То есть на проде масштабируется не весь лексический гибрид, а связка семантическая база + плант-скоуп. Эмбеддинги bge-m3 считаются на потребительском железе (Apple M1 Max, Metal-GPU) со скоростью ~15 эмб/с после перевода сборки индекса на батчевый /api/embed.

Гигиена данных (честно): анализ имён показал, что ~27.6% bulk-базы 2601 — артефакты HTML-ингеста ГН: 207 имён с «+» (в ГН это маркер «опасно через кожу», а не часть имени → дубли вроде «азотная кислота+»), 54 строки-контроли («б) контроль по формальдегиду» = метод, не вещество), 481 аномально длинное имя. Часть «промахов» top-1 — именно эти дубли/артефакты, а не провал ретрива (напр. на «...азотной кислоты на кожу» «правильно» победила кожная запись «азотная кислота+»). Verified-48 ядро (confidence = high/medium/low, не needs_review) — чистое: ни одного «+»/контроль-артефакта, проверено; все артефакты только в bulk needs_review (2553). Из 207 «+» лишь 3 — истинные дубли (азотная/бензол/серная кислота+), остальные 204 — реальные вещества с приклеенным маркером. Чистка (парсинг «+»→поле skin_hazard, слияние 3 дублей, пометка строк-контролей) — прямая работа аудит-спринта.

Ограничения этих цифр — не прятать. Метрика на 47 запросах показывает, что конвейер работает, и не показывает, что система готова к эксплуатации: настоящий eval — это десятки вопросов инженеров конкретного предприятия на его собственной базе. Полный разбор слабых мест (включая то, что документ-форма сгенерирована, а не оцифрована) — в LIMITATIONS.md.

Семантический кэш

L2 exact + L3 semantic. Параметрические запросы (номера партий, ID, даты) исключены из L3: «партия 42» и «партия 43» не кросс-кэшируются. Проверено (python3 engine/cache.py). Снижает стоимость эксплуатации, что важно для среднего завода.

Почему on-prem

Данные не покидают контур завода: Ollama локально, кэш и сервис on-prem. Подключение агента к ресурсам через MCP-границу доверия (ollama-mcp/), тот же паттерн, что Anthropic MCP Tunnels: узкие инструменты, белый список, аудит, исходящее соединение. Для химзавода с КИИ это и есть «AI через контролируемую границу, а не внутрь контура».

Деплой

# Локально: дефолты в коде указывают на канонические clean-файлы, переменные не нужны.
python3 -m pip install -r requirements/core.txt
python3 -m uvicorn service:app --app-dir engine --port 8012    # /docs — Swagger

# On-prem с живой моделью (семантический retrieval + grounded-генерация)
ollama pull bge-m3 && ollama pull qwen2.5:7b
python3 engine/build_semantic_index.py     # один раз: data/embeddings_clean.npy
RETRIEVER=semantic LLM_BACKEND=ollama OLLAMA_LLM=qwen2.5:7b \
  python3 -m uvicorn service:app --app-dir engine --port 8012

# Docker (контекст сборки — корень репозитория)
docker build -t hefest -f engine/Dockerfile .

Если эмбеддингов нет, сервис честно откатывается на лексику, а не падает. Полный on-prem стек (семантика, реранкер, OCR) — requirements/full.txt; развёртывание в закрытом контуре — DEPLOY.md.

Разовое обогащение приоритетных АХОВ: python3 engine/apply_enrich.py (оперативные поля), затем python3 engine/extend_corpus.py (инкрементальное расширение индекса без полного пересчёта).

Интерфейс: откройте home.html — это хаб, из него доступны консоль, аварийный экран, safety-хаб и шесть инструментов завода. В поле «сервис» укажите адрес запущенного бэкенда.

Ограничения

Коротко: данные документ-формы сгенерированы, а не оцифрованы с реальных паспортов; полнота базы низкая; лексический режим заметно слабее семантического; метрика на 47 запросах — иллюстрация, а не валидация. Развёрнуто и без смягчений — LIMITATIONS.md.

Это capability-proof: система собрана на реальных открытых данных, работает и меряется честно. Это не доказательство экономии у конкретного предприятия: на приватной грязной базе числа нужно переснимать.

Участие

Самый ценный вклад — сверка нормативного значения с бумажным первоисточником: для этого есть отдельный шаблон issue «Спор о нормативном значении». Порядок работы, требования к PR и святое правило проекта — в CONTRIBUTING.md.

make test     # офлайн-сьют
make guard    # предпубликационный сторож: секреты, .env, обезличивание
make check    # то и другое + компиляция

Об уязвимостях — приватно, см. SECURITY.md. Обход контура честности (заставить систему выдать значение без источника или пересчитать единицы) считается уязвимостью первого класса и принимается как вклад.

Лицензия

Код — MIT. Данные имеют собственное происхождение и условия: официальные нормативные значения РФ, материалы федеральных ведомств США в статусе public domain и сгенерированная форма паспорта — см. DATA-LICENSE.md.

Программа распространяется «как есть», без гарантий. Ответственность за применение в производственном контуре несёт эксплуатирующая организация — DISCLAIMER.md.

About

HEFEST — on-prem рабочее место по химической безопасности завода: паспорта ГОСТ 30333, аварийные карточки, зоны АХОВ, совместимость хранения, СИЗ, класс отхода. Поиск — фундамент, а не продукт. Офлайн, с провенансом, без выдуманной нормативки.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages