Заявка на поставку металлопроката и металлоконструкций на реальном рынке живет считанные часы. Снабженец строительного объекта отправляет ведомость одновременно в 4-5 заводов и заказывает у того, кто первым прислал официальное коммерческое предложение с точными ценами, весом и сроками отгрузки.
На производстве подготовка такого расчета занимает от 4 до 8 часов рабочего времени квалифицированного сметчика. Пока завод перебивает номенклатуру в Excel и сверяет коэффициенты, заказчик уже подписывает договор с более оперативным поставщиком.
Ниже технический разбор того, как мы автоматизировали этот процесс: почему популярная идея «скормить все в ChatGPT» приводит к прямому кассовому разрыву завода на сотни тысяч рублей, и как выглядит рабочая трехслойная архитектура на стыке Vision OCR, словарей ГОСТ и детерминированного кода.

1. Входящий хаос: как выглядит реальная заявка заказчика
В теории интеграторы любят рассуждать об электронном документообороте и структурированных XML-файлах. В реальности 90% входящих заявок - это информационный хаос:
Размытый скан проектной ведомости с наклонными строками и синей печатью поверх текста.
Фрагмент чертежа КМ/КМД, сфотографированный на телефон прямо со стройплощадки.
Разношерстный Excel от субподрядчика без артикулов и кодов 1С.
Простое сообщение в мессенджере с профессиональным сленгом закупщиков.
Типичный текст сообщения в отделе сбыта выглядит так:
«Добрый день! Нужен расчет на объект: уголок на сотку - 50 хлыстов по 12м, швеллер шестнашка П - 300 метров, лист четверка горячекатаный ст3сп - 15 квадратов, труба сотка стенка 4 - 1.2 км. Резка в размер. Жду расчет сегодня до 14:00.»
Чтобы превратить этот текст в официальный документ с печатью завода, инженер-сметчик выполняет длинную цепочку рутинных действий:
Переводит разговорный сленг («швеллер шестнашка П») в строгую нормативную номенклатуру («Швеллер 16П ГОСТ 8240-97»).
Открывает марочники и справочники стандартов, чтобы найти теоретическую массу одного погонного метра или квадратного метра.
Перемножает метры на нормативы ГОСТ, суммирует тоннаж, закладывает процент технологического отхода на раскрой (обычно 3-7%).
Заходит в 1С:УТ или ERP, проверяет фактические остатки на складе и актуальную закупочную цену за тонну.
Добавляет стоимость резки за рез, заводскую наценку, налоги и вручную верстает бланк коммерческого предложения в Word или Excel.
Когда за день в отдел продаж приходит 15 таких спецификаций, сметчики физически захлебываются в рутине.
2. Эксперимент: почему ChatGPT нельзя подпускать к расчетам
Первое, что приходит в голову разработчику при слове «нейросети» - написать промпт: «Вот текст ведомости заказчика, посчитай общую массу и итоговую сумму по нашему прайсу».
Мы провели чистый контролируемый тест на реальной ведомости металлопроката в модели GPT-4o. Скормили позицию:
«Швеллер 16П - 300 метров. Рассчитай теоретическую массу партии в тоннах.»
Результат генерации модели:

Модель бодро выдала красивое объяснение с формулами и вывела итог: 2,50 тонны.
Проверяем по государственному стандарту ГОСТ 8240-97 (Швеллеры стальные горячекатаные):
Теоретическая масса 1 погонного метра швеллера 16П составляет 14,20 кг.
Корректная масса партии: 300 м × 14,20 кг/м = 4 260 кг = 4,26 тонны.
Ошибка модели: 1,76 тонны в минус (занижение веса на 41,3%).
Если завод применит этот расчет при цене металла, например, 72 000 рублей за тонну:
Корректная себестоимость партии металла: 4,26 т × 72 000 ₽ = 306 720 ₽.
Себестоимость по расчету ChatGPT: 2,50 т × 72 000 ₽ = 180 000 ₽.
Прямой кассовый убыток предприятия на одной позиции: 126 720 рублей.
Почему языковая модель так ошибается?
Языковая модель - это вероятностный генератор токенов, а не детерминированный калькулятор. Она помнит, что у слова «швеллер» в обучающей выборке часто встречались цифры 8, 10, 14, 16, 20. В процессе предсказания следующего токена она берет правдоподобную плотность стали или справочный вес соседнего типоразмера (например, швеллера 10П или 12П с массой ~8,59 кг/м) и с абсолютной уверенностью выдает галлюцинацию за чистую монету.
Доверять языковой модели арифметику, физические единицы измерения и расчет денег на производстве категорически запрещено.
3. Архитектура рабочего конвейера
Чтобы исключить человеческий фактор и при этом гарантировать нулевой процент галлюцинаций в цифрах, мы разделили обработку заявки на три строго изолированных контура:

Слой 1. Семантический парсинг и нормализация номенклатуры (Vision + LLM)
Нейросеть решает ровно ту задачу, для которой она создана: работает с неструктурированным языком и сложной геометрией документов. Никакой математики на этом слое нет.
Предобработка сканов (OpenCV):
Выравнивание угла наклона листа (deskew через преобразование Хафа).
Нормализация контраста и приглушение синего канала печатей в цветовом пространстве HSV (без жесткой бинаризации, чтобы не убить полутона и градиенты для мультимодальной сети).
Извлечение таблиц:
Мультимодальная модель (Vision API) анализирует разметку документа. В отличие от Tesseract OCR, мультимодальные модели понимают контекст объединенных ячеек, нестандартные заголовки граф и рукописные приписки снабженцев на полях.
Нормализация через системный промпт со строгой схемой: Модель извлекает семантику: семейство проката, калибр и единицы измерения. При этом сам номер стандарта модель не придумывает - точный ГОСТ подтягивается жестким кодом на Слое 2 из реестра соответствий по связке семейства и размера профиля (например,
channel+16Поднозначно мапится вГОСТ 8240-97). Это гарантирует, что модель не подставит устаревший или выдуманный стандарт.
{ "name": "parse_specification_items", "description": "Извлечение позиций металлопроката и параметров заказа", "parameters": { "type": "object", "properties": { "items": { "type": "array", "items": { "type": "object", "properties": { "raw_text": { "type": "string", "description": "Исходный текст позиции из заявки" }, "standard_family": { "type": "string", "enum": ["channel", "angle", "beam", "sheet_hot", "pipe_round", "pipe_profile"], "description": "Семейство проката для маппинга на стандарт" }, "profile_size": { "type": "string", "description": "Калибр/размер, например 16П, 100х100х8" }, "steel_grade": { "type": "string", "description": "Марка стали, например Ст3сп5, 09Г2С" }, "quantity": { "type": "number", "description": "Числовое значение объема" }, "unit": { "type": "string", "enum": ["meters", "tons", "pieces", "sq_meters"] }, "cut_length": { "type": ["number", "null"], "description": "Длина реза/хлыста в метрах, если явно указана для позиции" } }, "required": ["raw_text", "standard_family", "profile_size", "quantity", "unit", "cut_length"] } } }, "required": ["items"] } }
Модель выдает типизированный JSON. Фраза «швеллер шестнашка П - 300 метров» (где длина хлыста для резки не была задана) преобразуется в валидный объект с cut_length: null:
{ "raw_text": "швеллер шестнашка П - 300 метров", "standard_family": "channel", "profile_size": "16П", "steel_grade": "Ст3сп", "quantity": 300, "unit": "meters", "cut_length": null }
Слой 2. Детерминированный расчетный движок (Python + Справочники ГОСТ)
Второй слой - это полностью детерминированный код без использования нейросетей. В систему загружена локальная реляционная база справочных весов по всем государственным стандартам РФ.
Фрагмент расчетного модуля на Python:
from decimal import Decimal, ROUND_HALF_UP # Детерминированный реестр стандартов по семейству проката (исключает галлюцинации LLM) FAMILY_TO_GOST = { "channel": "ГОСТ 8240-97", "angle": "ГОСТ 8509-93", "beam": "ГОСТ 26020-83", "sheet_hot": "ГОСТ 19903-2015", "pipe_round": "ГОСТ 10704-91", } # Справочные коэффициенты погонной массы по ГОСТ 8240-97 (кг на 1 метр) GOST_8240_97_WEIGHTS = { "10П": Decimal("8.59"), "12П": Decimal("10.40"), "14П": Decimal("12.30"), "16П": Decimal("14.20"), "18П": Decimal("16.30"), "20П": Decimal("18.40"), "24П": Decimal("24.00"), } def calculate_item_cost(item: dict, warehouse_price_per_ton: Decimal, markup_ratio: Decimal = Decimal("1.12")): """ Строгий расчет массы и стоимости позиции с контролем размерностей. Метры * (кг/м) = кг -> кг / 1000 = тонны -> тонны * (руб/т) = рубли. """ family = item["standard_family"] standard_code = FAMILY_TO_GOST.get(family) if not standard_code: raise ValueError(f"Неизвестное семейство проката: {family}") size = item["profile_size"] qty = Decimal(str(item["quantity"])) unit = item["unit"] if standard_code == "ГОСТ 8240-97": weight_per_meter = GOST_8240_97_WEIGHTS.get(size) if not weight_per_meter: raise ValueError(f"Размер {size} не найден в справочнике ГОСТ 8240-97") if unit == "meters": total_weight_kg = qty * weight_per_meter total_meters = qty elif unit == "tons": total_weight_kg = qty * Decimal("1000") total_meters = total_weight_kg / weight_per_meter else: raise NotImplementedError(f"Единица измерения {unit} требует дополнительных параметров") total_weight_tons = (total_weight_kg / Decimal("1000")).quantize(Decimal("0.001"), rounding=ROUND_HALF_UP) # Расчет себестоимости партии и цены с учетом наценки base_cost = total_weight_tons * warehouse_price_per_ton final_price = (base_cost * markup_ratio).quantize(Decimal("1"), rounding=ROUND_HALF_UP) return { "standard_title": f"Швеллер {size} {standard_code} / {item.get('steel_grade', 'Ст3сп')}", "meters": float(total_meters), "weight_tons": float(total_weight_tons), "base_cost_rub": float(base_cost), "final_price_rub": float(final_price) }
Актуальные складские остатки сырья и базовая себестоимость подтягиваются из 1С:ERP через стандартный REST API по коду номенклатуры. Алгоритм не имеет права фантазировать: если нужной марки стали нет на складе, позиция помечается флагом requires_procurement.
Слой 3. Human-in-the-loop и сборка официального PDF
Ни одно реальное производство с многомиллионными контрактами не выпустит документ клиенту в полностью автоматическом режиме без участия инженера.
Конвейер формирует проект коммерческого предложения за 15-20 секунд и отображает его сметчику в удобном интерфейсе:
Зеленый статус: позиции, которые распознаны с уверенностью 99%+ и имеют полное совпадение по номенклатуре склада.
Желтый статус: позиции, где в исходном скане была неразборчивая цифра либо нестандартный раскрой. Сметчик тратит 30 секунд на сверку сомнительной строки.
Генерация чистового КП: после подтверждения инженером движок рендерит официальный PDF-документ на фирменном бланке завода со сквозной нумерацией, таблицей ГОСТ, условиями доставки, факсимиле подписи и круглой печатью организации.
Готовый файл автоматически прикрепляется к сделке в CRM (Битрикс24 или AmoCRM), а ссылка на скачивание отправляется клиенту в WhatsApp или на почту.

4. Сравнение производительности: до и после
Мы замерили результаты работы сметного отдела завода до и после внедрения расчетного конвейера на выборке из 350 входящих промышленных спецификаций:
Параметр | Ручной расчет инженера | Автоматизированный конвейер |
|---|---|---|
Время подготовки 1 КП | 4 - 8 рабочих часов | 20 - 30 секунд на генерацию + 2 мин на валидацию |
Вычисление массы | Ручной поиск по бумажным справочникам и формулам в Excel | Детерминированный расчет по базам ГОСТ |
Риск ошибки в тоннаже | До 8-12% из-за опечаток и усталости к концу дня | 0% (алгоритмическая проверка единиц) |
Роль сметчика | Монотонная перебивка строк со сканов в таблицы | Экспертный контроль сомнительных позиций |
Скорость ответа клиенту | На следующий рабочий день (сделка часто теряется) | В течение 10-15 минут после обращения |
Нагрузка на отдел сбыта | Максимум 8-10 сложных расчетов в день на отдел | До 200 спецификаций в смену без расширения штата |
5. Как протестировать логику самостоятельно
Чтобы проверить, как связка Vision-модели и детерминированных словарей ГОСТ отрабатывает на нестандартных таблицах и чертежах без необходимости поднимать контур локально, я собрал открытую песочницу-демо: samartsev.tech/kp.
Там можно загрузить собственный скан спецификации металлопроката, фото чертежа или Excel-таблицу без регистрации и посмотреть, как сырые строки раскладываются на чистые позиции стандарта с расчетом массы и себестоимости.
Резюме
Большие языковые модели отлично работают как универсальный транслятор человеческого языка, нечетких сканов и разношерстных таблиц в строгие структуры данных. Но как только дело доходит до физики, ГОСТов и рублей, управление должно немедленно передаваться детерминированному коду.
Такая связка превращает рутинный рабочий день сметчика в двухминутный контроль готового черновика и позволяет предприятию забирать контракты первыми.
Автор: Алексей Самарцев (samartsev.tech). Обсудить архитектуру пайплайна и нюансы нормализации можно в комментариях или в Telegram: @samartsev_ai.
