Как мы убрали галлюцинации ИИ из коммерческих предложений
КПилот собирает коммерческое предложение из прайса и короткого брифа за пару минут. Первое, что стало ясно ещё на тестах: языковой модели нельзя доверить ни одной цифры. Не потому что модель слабая, а потому что она не считает, а продолжает текст. Рассказываем, как устроена архитектура, которая позволяет использовать ИИ для прозы и при этом гарантирует, что в документе не появится выдуманная сумма.
Почему цифры от нейросети опасны именно в КП
Коммерческое предложение с ценой и существенными условиями признаётся офертой (статья 435 ГК РФ). Если клиент его принимает, договор считается заключённым на указанных условиях. За сумму отвечает тот, кто отправил документ, а не нейросеть.
Модель предсказывает следующее слово. Для прозы это работает: она держит тон и структуру. Для чисел это провал. У модели нет вашего прайса, наценок и минимальной маржи, поэтому она подставляет число, которое статистически уместно рядом с такими словами. Классический случай из наших ранних прогонов: в смете 380 000, а в тексте «итого 290 000», потому что так «ровнее звучит». Формально модель не ошиблась в арифметике. Она вообще не делала арифметику.
Почему «дай модели источники» не решает проблему
Подход с подсказками из базы знаний (retrieval) помогает, но не закрывает риск целиком: на практике модель нередко сначала фиксирует ответ, а потом подбирает под него подходящую цитату. Мы вывели для себя простую иерархию надёжности.
- Число, посчитанное кодом: детерминировано и воспроизводимо.
- Факт, процитированный из проверенного источника с привязкой к нему.
- Просто сгенерированный текст.
Разделение конвейера: две независимые ветки
Мы разложили генерацию КП на две ветки. Детерминированная ветка: движок расчёта берёт услуги и ставки из прайса организации, применяет правила (наценки, скидки, порог минимальной маржи, округление) и возвращает снимок расчёта. Один и тот же вход всегда даёт один и тот же результат.
Генеративная ветка: нейросеть пишет прозу по секциям, но вместо конкретных сумм оставляет размеченные места. На этапе сборки код подставляет в эти места значения из снимка расчёта. Ключевой инвариант: модель не видит финальные числа и не производит их. «Выдумать» цену негде, потому что в тексте модели её просто нет.
Себестоимость и маржа живут только внутри движка. Они нужны, чтобы предупредить продавца о работе в минус, но в запрос к модели и в итоговый документ не попадают никогда.
Проверка перед выдачей
Даже с разделением веток модель иногда протаскивает число или факт в прозу. Поэтому перед выдачей каждый документ проходит отдельную проверку.
- Собирается список допустимых сумм из расчёта; любая денежная величина в тексте сверяется с ним. Сумма вне расчёта отбраковывается.
- Кейсы и отзывы принимаются только с привязкой к источнику из вашей базы знаний.
- Из прозы вычищаются служебные идентификаторы, если модель случайно их протащила.
- Тонкость: «120 м²», «20%» и «5 штук» это не деньги. Наивный поиск чисел давал ложные срабатывания, пришлось исключать величины с единицами измерения.
Происхождение каждого факта
Чтобы всё это можно было проверять и объяснять, каждый факт в документе несёт метку происхождения: данные продавца (услуги, реквизиты, кейсы), значения из детерминированного расчёта, или проза, написанная моделью. По этой разметке проверка понимает, что сверять строго, а где допустима свобода формулировок. Клиент на странице предложения видит отметку, что документ прошёл проверку.
Что мы поняли по дороге
- Детерминизм выглядит скучно, зато под таким документом можно подписывать договор. Это важнее «вау-эффекта» от генерации.
- «Взять модель помощнее» не убирает числовые ошибки: меняется качество прозы, а не природа галлюцинаций в цифрах. Помогает архитектура, где число приходит из кода.
- Проверка окупается и как регрессионный тест: когда мы меняли промпты, именно она поймала, что модель начала протаскивать проценты и площади в неожиданных местах.
- Вывод переносится на любой продукт, где ИИ генерирует документы с последствиями: доверяйте модели слова и не доверяйте ей числа и факты, за которые потом отвечать вам.
Частые вопросы
Что такое галлюцинации нейросети?
Уверенная генерация несуществующих фактов: выдуманные цены, скидки, кейсы, характеристики. Модель не проверяет утверждения, а подбирает правдоподобное продолжение текста, поэтому ошибка выглядит убедительно.
Можно ли полностью убрать галлюцинации промптом?
Нет. Промпт снижает частоту, но не меняет природу модели. Надёжно работает архитектура: цифры считает код из прайса, факты берутся из базы с источником, а перед выдачей документ проходит автоматическую проверку.
Чем детерминированный расчёт отличается от генерации?
Детерминированный расчёт выполняет код: одинаковый вход всегда даёт одинаковый результат, и его можно проверить. Генерация выдаёт правдоподобный текст, который каждый раз может отличаться и не обязан быть верным.
Как проверить КП, сделанное нейросетью?
Сверить каждую сумму с прайсом и итог с расчётом, проверить реальность кейсов, убрать невыполнимые обещания. В КПилоте эта проверка автоматическая: цифры вне расчёта и факты без источника отбраковываются до выдачи документа.