Советчик оператору цепочки АВТ → гидроочистка → смешение дизельного топлива.
Мультиагентная система проверяет данные, прогнозирует серу, сравнивает планы
и выдаёт рекомендацию, сохранение режима или объяснённый отказ.
Решение задеплоено и доступно онлайн:
neftecode.goatwhistle.ru
В Docker развёрнуто решение с агентным слоем, который работает через LLM. LLM помогает проводить разбор условий, выбирать действия и объяснять результат, а детерминированное ядро, Gate и жёсткие ограничения проверяют каждого кандидата и не позволяют модели ослабить требования.
Если нужен полностью детерминированный прогон без внешней модели и ключа,
в .env укажите:
AGENTIC_DECISION_ENABLED=0
LLM_PROVIDER=scriptedВ этом режиме решение принимает детерминированное ядро по правилам и расчётным моделям; LLM не вызывается. Шаблон настроек находится в .env.example. Решение задеплоено: https://neftecode.goatwhistle.ru/
Система работает на реальных данных завода: 189 217 десятиминутных строк телеметрии за 2023–2026 годы, лабораторные анализы ЛИМС и поточный анализатор ПАК. Название — из термина перегонки: cut point, температура отсечки, граница между фракциями. Система проводит такую же границу между допустимым и недопустимым.
|
① Каждое число знает У любой величины есть метка:
Расчёт, которому нужен |
② Отказ — это ответ, Если данные непригодны или допустимого плана нет, система говорит об этом и называет, какое измерение изменило бы вердикт. На срезе 16.04.2026 с устаревшей
лабораторией ответ — |
③ LLM не может ослабить Агенты выбирают из заранее допустимых вариантов; жёсткие пределы проверяет детерминированный контур. При недоступности модели решение принимается без неё — с явной пометкой в результате. |
ДАННЫЕ ПРОВЕРКА ПРОГНОЗ
├─ телеметрия АВТ ├─ возраст ├─ сера после ГО
├─ телеметрия 24-2000 ├─ пропуски ──▶ ├─ интервал
├─ ЛИМС (+4 ч) ──▶ ├─ зависание └─ отклик на T6
└─ ПАК └─ конфликт │
▼
ОТВЕТ ОПЕРАТОРУ ВЫБОР ПЛАНА КАНДИДАТЫ
├─ hold выпуск ├─ постоянные планы
├─ recommend_scenario → стоимость ◀── ├─ переходные планы
└─ refuse ◀── → тяжесть └─ Gate: сера ≤10 мг/кг,
+ причина → число изменений доли 100%, уставки,
+ что изменило бы запасы, резервуары
решение ▲
│
АГЕНТЫ (поверх ядра)
Orchestrator · Quality · Reliability
только ужесточают ограничения и veto
Подробный разбор каждого этапа — docs/pipeline.md.
Схема расчёта: контур данных, контур решения и слой агентов.
Каждый узел раскрывается и показывает, что именно этап посчитал;
пунктиром — ветви отказа, которые на этом прогоне не сработали.
Нужны Python 3.12 и uv. Все команды — из корня проекта. Внешние API и ключи не нужны: расчёт целиком локальный.
uv sync --frozen
AGENTIC_DECISION_ENABLED=0 uv run neftecode serveОткрыть http://127.0.0.1:8765/ — и пройти пять шагов:
1 · Выбрать сцену и нажать «Запустить расчёт» Норма, риск качества или плохие данные. Этапы приходят по мере счёта через SSE, работа агентов видна событиями.
2 · Раскрыть узел 00 схемы Условия расчёта, у каждого числа — бейдж происхождения.
3 · «Закрепить для сравнения» → «Что изменится, если…» Отключить источник или резервуар и получить парное сравнение — с оговорками о несопоставимости срезов, моделей и горизонтов.
4 · «Карта компромиссов» Недоминируемое множество по выпуску, стоимости и тяжести режима.
5 · «Скачать протокол» или «Открыть запись» JSON с контрольной суммой; запись проигрывается заново, без обращения к расчёту и LLM.
Другие способы запуска — тесты, агенты без LLM, Docker
Проверка тестами — 1551 тест, внешняя сеть не нужна:
LLM_PROVIDER=scripted uv run pytest -qАгентный протокол без языковой модели. scripted подставляет заранее написанную
политику выбора инструментов: показывает механику агентов, но не доказывает пользу LLM.
uv run neftecode agent-demoЧерез Docker:
docker compose up --build
docker compose -f docker-compose.offline.yml up --build # закрытый контурЧетыре отдельных процесса — data 8766, model 8767, decision 8768, gateway 8765:
uv run neftecode-stack --root . --artifacts artifactsЕсли вы открыли репозиторий впервые и хотите понять решение, а не читать всё подряд:
| Вопрос | Файл | Что там |
|---|---|---|
| Как устроено решение | docs/architecture.md | Слои, контракты, цикл агентов |
| Где какой код | docs/code-tour.md | Карта модулей: с чего начать чтение |
| Что происходит при расчёте | docs/pipeline.md | Конвейер от входа до ответа, по фактическому коду |
| Выполнено ли ТЗ | docs/requirements-map.md | Пункт ТЗ → модуль → тест → статус и границы |
| Насколько точен прогноз | docs/forecast-evidence.md | Протокол, rolling-проверка, финальная оценка 2026 |
| Откуда взялся отклик на T6 | docs/response-model.md | Оценка β, интервал, область применимости |
| Какие периоды выброшены и почему | docs/excluded-periods.md | Реестр с воспроизводимой командой |
| Все зафиксированные эксперименты | research/README.md | Методики, сырые результаты, границы |
| Контракты HTTP-сервисов | docs/services.md | Четыре процесса, порты, протокол |
Если хотите прочитать код — в таком порядке:
src/neftecode/application/use_cases/decision/— цикл принятия решения целиком. ЗдесьMakeDecision, Gate и обзоры качества и надёжности.src/neftecode/domain/— сущности предметной области: планы, партии резервуаров, ограничения. Зависимостей наружу нет.src/neftecode/infrastructure/data/— загрузка источников, синхронизация по времени, правила доверия.src/neftecode/services/— четыре HTTP-процесса и поток/api/stream.
203 модуля разложены на domain, application, infrastructure, evaluation,
presentation, services, composition. Направления зависимостей — не договорённость,
а тест: AST-проверки в tests/architecture/ падают, если слой нарушит границу.
Интерфейс — src/frontend/ (разработка). Собранная версия
входит в Git, поэтому Node.js для запуска не нужен.
|
Прогноз серы после гидроочистки MAE 1.802 → 1.616 мг/кг Последний пригодный ПАК с медианной поправкой по 20 доступным парам ЛИМС−ПАК. Метод выбран на пяти rolling-периодах до 2026 года, затем один раз проверен на 2026 — на одинаковых 233 пробах. |
Отклик серы на температуру реактора β = −0.4227 мг/кг/°C Доверительный интервал [−0.4768; −0.389]
с объявленной областью применимости.
Оценивается по |
Пороги доверия к источникам выведены из истории, а не заданы руками. ТЗ требует проверку данных, но конкретных чисел не даёт — мы посчитали их по обучающему периоду:
| Правило | Порог | Откуда |
|---|---|---|
| ЛИМС устарел | старше 48 ч | два суточных интервала отбора проб |
| ПАК устарел | старше 30 мин | три периода опроса |
| Датчик завис | 4 одинаковых показания подряд | так редко бывает у живого прибора |
| Конфликт ПАК–ЛИМС | расхождение выше 4.75 мг/кг | 95-й перцентиль расхождения |
| Телеметрия неполна | от 10 пропавших датчиков из 96 | провал между режимом и сбоем опроса |
Шесть сцен демонстрации (на комплекте с сохранёнными срезами):
| Сцена | Момент | Ответ ядра |
|---|---|---|
| Нормальный режим | 05.01.2026 08:00 | hold |
| Ухудшение сырья | синтетическая | hold |
| Зависший анализатор | 20.07.2026 19:10 | hold с резервным источником |
| Устаревшая лаборатория и сломанный ПАК | 16.04.2026 10:10 | refuse |
| Резервуар выведен из работы | реальный срез + изменение доступности | recommend_scenario |
| Риск ухудшения качества | 24.07.2026 03:00 | recommend_scenario |
Изменение входа не обязано менять действие: если текущий режим допустим, а выгода мала, система сохраняет его. Это намеренное поведение, а не отсутствие реакции.
Карта обмена строится во время прогона: слева оркестратор, справа специалисты,
рядом с каждым — инструменты, которые агент выбрал сам. Стрелка к специалисту — запрос,
обратно — вердикт. Здесь оба специалиста дали ACCEPT, и план hold прошёл.
Система отвечает одним из трёх исходов, и каждый выглядит по-своему.
Сохранить режим. Текущий режим проходит все 218 обязательных проверок,
выгода от вмешательства не покрывает риск — система не трогает установку.
Под вердиктом: номинальные проверки, устойчивость к отклонениям и граница применимости.
Решение не выдано. Отказ назван числом, а не общей фразой: сера 25,243 мг/кг
против предела 10 на всём интервале 0 — 2 ч. Сказано и то, что режим остаётся прежним,
и что риск, из-за которого план не найден, никуда не делся.
Третий исход — изменить режим: система предлагает конкретный план с уставками,
когда он и допустим, и заметно лучше текущего. На сценарных данных он выпадает реже двух
других: если текущий режим проходит проверки, система намеренно его не трогает.
Планировщик строит постоянные и переходные планы, считает качество, массовый баланс, выпуск, условную стоимость и тяжесть режима. Gate проверяет серу ≤10 мг/кг, объявленные свойства продукта, доли компонентов (сумма = 100%), границы уставок, доступность компонентов и ограничения запасов. Неизвестное обязательное условие не считается выполненным.
Парк резервуаров моделируется партиями по стадиям filling → awaiting_passport → ready → draining: проверяются вместимость, 12 часов паспортизации, предел слива за 24 часа,
массовый баланс и прогноз паспорта наливаемой партии.
Порядок выбора плана: выпуск → стоимость → тяжесть режима → число изменений →
идентификатор. Политика min_useful_gain удерживает текущий режим при малой экономии.
Поиск дискретный с бюджетом 1200; глобальная оптимальность не заявляется.
Агенты. OrchestratorAgent, QualityAgent и ReliabilityAgent работают поверх ядра.
Специалисты получают ограниченный набор инструментов и возвращают мнения со ссылками на
результаты. Код применяет только разрешённые ужесточения и veto — ослабить ограничение
агент не может. Финальный план перепроверяется. Если ошибка случилась после принятого
ограничения, fallback сохраняет ограничение и выбирает оставшийся план либо отказывает.
По умолчанию агентный слой включён с провайдером Z.AI; AGENTIC_DECISION_ENABLED=0
отключает его, LLM_PROVIDER=local переключает на локальный OpenAI-совместимый endpoint.
Ключи — в окружении или локальном .env, в Git не входят. Живые вызовы занимают минуты;
temperature=0 не гарантирует повторяемость внешней модели.
Четыре процесса запускает uv run neftecode-stack: data 8766, model 8767,
decision 8768, gateway 8765. Gateway реализует /api/stream и передаёт этапы и события
агентов по мере расчёта. HTTP-протокола отмены у decision-service нет: кнопка прекращает
показ, сервер может продолжать счёт.
Команда uv run neftecode … |
Что делает | Нужен task/ |
|---|---|---|
serve |
Интерактивная демонстрация: страница, изменение условий, поток расчёта | нет |
scenes |
Пять синтетических сцен, шесть при наличии срезов | нет |
screen --scenario config/scenarios/sour_crude.json |
Экран оператора по одному сценарию | нет |
benchmark |
Шесть сценариев: hold, пороговое правило, советчик, две абляции | нет |
agent-demo |
Четыре сценария scripted-политики: трасса выбора инструментов | нет |
advise --at 2026-01-05T08:00:00 |
Решение на исторический момент | да + model.pkl |
train |
Обучение, временная проверка прогноза, отклика и порогов доверия | да |
snapshot --all |
Заморозить срезы из config/snapshot_moments.json |
да + model.pkl |
vak |
Проверка 17 формул виртуальных анализаторов | да |
episodes |
Статистика превышений ПАК и предупреждений | да |
tank-check |
Сверка оценок серы потока и окна с ЛИМС | да |
expert-grid |
Перебор изменяемых условий демонстрации | нет |
--out меняет каталог результатов и загружаемых оттуда моделей и срезов.
Выданный организаторами каталог task/ и каталог artifacts/ в Git не входят.
Чистый клон отличается от полного архива сдачи — и система сообщает об этом сама,
а не показывает синтетику под видом реального среза.
| Комплект | Что доступно |
|---|---|
| Чистый клон | Синтетические сцены, benchmark, agent-demo, интерфейс |
+ artifacts/ (срезы, manifest, response_model, source_rules) |
Демонстрация на сохранённых исторических состояниях |
+ task/ и совместимый model.pkl |
Исторический advise, построение срезов, исследования |
| + обучение | Переобучение, отчёты, модель и пороги доверия |
Ожидаемая структура исходного пакета:
task/
data/avt_tags.csv телеметрия АВТ (71 сигнал)
data/242000_tags.csv телеметрия 24-2000 (26 сигналов)
ЛИМСы ... .xlsx лабораторные анализы
Выгрузка ПАК ... .xlsx поточный анализатор
Теги_хакатон.xlsx справочник тегов
ТЗ_нефтекод.docx
АВТ_схемы.pdf
2026-09-16/теги АВТ_24-2000.xlsx уточнённый справочник
2026-09-16/формулы_ВАК.xlsx
Телеметрия — 189 217 строк с шагом 10 минут, 01.01.2023–07.08.2026. ЛИМС и ПАК имеют собственные временные сетки; синхронизация только по времени, никогда по номеру строки. Для ЛИМС принята консервативная задержка публикации 4 часа, чтобы будущее знание не попало в решение. Служебные индексы не используются как признаки.
ЛИМС — контрольный факт; неисправный ПАК не считается достоверным. Происхождение правил
доверия показывается прямо в результате: derived:artifacts/source_rules.json или
fallback:config/experiment.json.
Исключённые периоды (остановки, сбои опроса, зависание ПАК, конфликт ПАК–ЛИМС) задокументированы и воспроизводятся одной командой:
uv run python scripts/excluded_periods.py --root <каталог с task/>Для класса «плановые остановки установки» в данных нет отдельного флага — это указано в реестре как ограничение, а не домысленный список дат.



