← Проекты

Proof of concept · Розница стройматериалов

Каждая фраза ассистента магазина — это оферта.

Ассистент в мессенджере поверх каталога магазина стройматериалов на 13 312 позиций, запущенный как proof of concept вместе с владельцем. Смысл был не в демонстрации, а в том, чтобы выяснить, какие фразы этой системе нельзя позволять произносить.

Роль
Product lead и разработка
Стек
Python · инвертированный индекс в памяти · агент с инструментами
Статус
Proof of concept подтверждён · клиент анонимизирован по его просьбе
Почему здесь ставка иная

Ошибающийся чат-бот на сайте — это неловко. В магазине он связывает обязательством.

Бразильское потребительское право считает достаточно точную информацию, переданную любым способом, обязывающей поставщика и входящей в договор. Когда ассистент, говорящий от имени магазина, называет цену, напряжение или мощность, магазин за это отвечает. Я не юрист, и тут нужен юрист, но направление достаточно ясное, чтобы проектировать с его учётом.

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

Первое ограничение

Модель никогда не видит каталог.

Очевидное решение в 2026 году — векторное хранилище и цепочка retrieval. Предыдущая попытка пошла этим путём через workflow-инструмент и умерла на таймаутах, потому что помещать тринадцать тысяч строк рядом с промптом — это не стратегия поиска.

Поэтому каталог полностью остаётся вне модели. Тринадцать тысяч товаров загружаются в память за инвертированным индексом и отвечают за одну–пять миллисекунд. Без базы данных — тринадцать тысяч строк помещаются в RAM, а Postgres заслуживает своё место только при реальной конкурентности. Модель получает восемь строк и пишет ответ вокруг них.

Трудным был не индекс, а словарь. Каталог написан сокращениями ERP, а клиент говорит языком прилавка: арматура заведена под названием, которое вслух никто не произносит, а каменщик, просящий «балерину», имеет в виду корончатое сверло. Этот разрыв закрывает слой синонимов, и правая часть каждого сопоставления обязана существовать в реальном каталоге — иначе сопоставление превращается в ложь, похожую на починку.

Размеры типизированы, фильтр жёсткий

25 мм никогда не вернёт 32 мм. Лучше сказать, что у нас такого нет.

Каждый размер разбирается на значение и размерность, поэтому 18 литров краски никогда не сравниваются с 18 мм трубы. Дюймы намеренно держатся отдельной размерностью от миллиметров: четверть дюйма трубы — это 20 мм, четверть дюйма арматуры — 6,3 мм, и слияние этих двух ставило не тот пруток на первое место.

Поле единицы измерения в ERP содержит 136 различных значений, поэтому оно повторяется дословно и никогда не интерпретируется. Спутать банку 0,9 литра с банкой 3,6 — это не погрешность округления, это спор у прилавка.

Что обнаружил proof of concept

Поиск перестал врать. Тот, кто пишет ответ, — нет.

Вывод модели из поиска сработал: за все сессии поиск не вернул неверный товар. Это обнажило другое: оставшаяся поверхность — превращение восьми строк во фразу — выдумывает ровно там, где каталог молчит. Четыре поведения, все наблюдались:

Назвал характеристики, которых не существует

На вопрос о подробностях по насосу ассистент описал тип двигателя, назначение и напряжение питания. Ничего этого нет в каталоге, где есть описание, цена и остаток. На следующий день на прямой вопрос о напряжении тот же ассистент верно ответил, что в системе его нет. Один вопрос, противоположные ответы, и выдуманный прозвучал первым.

Прочитал описание вместо поля

Товар, в названии которого были четыре ступени и две лошадиные силы, в ответе превратился в насос на четыре лошадиные силы — и эта выдуманная цифра тут же пошла в сравнение моделей для клиента. Это число никогда не было полем; это была строка, которую модель истолковала.

Сначала согласился, потом проверил

Клиент упомянул линейку товаров, о которой слышал. Ассистент объяснил, как она работает, поддержал её как подходящий вариант и лишь затем выполнил поиск и выяснил, что магазин её не продаёт. Одобрение уже прозвучало.

Когда инструмент отказал, начал импровизировать

Инструмент подбора дважды выдал ошибку. Вместо остановки ассистент выдал собственную рекомендацию. Это ровно тот отказ, ради предотвращения которого инструмент и существует.

Что proof of concept произвёл

Пять ограничений, написанных из четырёх отказов.

Это и есть результат. Не демонстрация, которая кого-то впечатлила, а спецификация того, что ассистенту должно быть запрещено, где каждая строка прослеживается до того, что он действительно сделал.

  1. 01

    Опора на данные, проверяемая детерминированно

    Ответ может утверждать только те атрибуты, что есть в найденных строках. Это закрепляется дважды: контрактом в промпте и проверкой после генерации, которая извлекает утверждения и сверяет их с полезной нагрузкой. Проверка детерминированная намеренно — я уже строил панель оценки, где судьёй была модель, и видел, как она одобряет почти всё, включая плохой результат. Модель, спрашивающая модель, не выдумала ли та, наследует ту же проблему, которую должна ловить.

  2. 02

    Типизированные атрибуты, а не истолкованная строка

    Ступени, мощность и напряжение становятся типизированными полями на этапе индексации — так же, как уже сделано с размерами, — и пишущий слой получает поля, а не описание для чтения. Этот приём в системе уже есть: именно поэтому дюймы и миллиметры разведены по размерностям. Его просто не распространили на атрибуты, спрятанные в названии товара.

  3. 03

    Сначала поиск, потом утверждение

    Никаких заявлений о том, что есть в магазине или как работает названный товар, пока в этом же ходе не вернулся результат поиска. Порядок обеспечивается в цикле агента, а не просьбой в промпте.

  4. 04

    Отказавший инструмент останавливает

    Если инструмент подбора выдал ошибку, ассистент говорит, что сейчас не может проверить, и предлагает человека. Он не подменяет собственным суждением инструмент, который существует именно потому, что его суждения недостаточно.

  5. 05

    Подбор по размеру остаётся в проверенном диапазоне

    Рекомендация, рассчитанная от площади помещения или числа точек, — это совет с физическими последствиями, поэтому она ограничена: вернуть наименьшее оборудование, покрывающее требование, отказать за пределами проверенного диапазона и передать человеку вместо экстраполяции.

И ещё одно, но это не ограничение

Сохранять то, что было показано клиенту.

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

Что это доказывает, а что нет

Честное чтение

Это был proof of concept, проведённый с владельцем, а не с публикой, и анонимизированный по его просьбе. Нет ни цифры выручки, ни развёртывания, на которое можно указать. Перечисленные ограничения — это спецификация, которую произвёл сам эксперимент; построены ещё не все.

Он показывает решение, которое большинство не приняло бы, — оставить модный инструмент вне той самой части системы, куда его сегодня ставят все, — и затем дисциплину пойти искать, где это решение оказалось недостаточным, вместо того чтобы остановиться на сработавшей демонстрации.

Думаете поставить ассистента перед клиентами?

Полезный разговор обычно о том, какие фразы ему нельзя позволять произносить.