Как я научил LLM попадать в 1С с первого раза

от автора

В пятницу вечером менеджер получает письмо: нужно 200 метров ВВГ 3х2.5, не плоский. Открывает 1С, вбивает запрос и видит 47 позиций. Какой из них круглый, а какой плоский? Какой с оболочкой ок-0.66, а какой по ТУ? Ошибёшься и на стройке машину развернут.

На одну позицию уходит 4–7 минут. Пять позиций в заявке, двадцать заявок в день. К концу недели уже не в номенклатуру смотришь, а в стену.

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

Почему регулярки и Левенштейн сразу сдают Первый порыв написать парсер: вытащить марку, сечение, исполнение и через ILIKE найти кандидатов. На бумаге красиво, на реальных заявках нет.

Клиенты пишут как хотят: ВВГ-3*2,5, провод ВВГнг 3 на 2.5, ВВГ 3×2,5 не круглый. При этом «не плоский» у нас означает как раз круглый, потому что плоский — это ВВГ-П. Левенштейн путает 3х2.5 с 3х4 (разница в цене в два раза), а полнотекстовый поиск отдаёт те же 47 вариантов.

Двухступенчатая схема Шаг 1. Векторное отсеивание Прогоняем всю номенклатуру через эмбеддинг-модель, нормализуем строки (убираем лишние пробелы, приводим «х» и «×» к одному виду, разворачиваем сокращения) и складываем в pgvector. Запрос клиента проходит ту же обработку.

Ищем по косинусной близости, берём топ-15. Задача просто отсеять 11 985 заведомо не тех позиций.

Шаг 2. LLM как дешифратор Топ-15 отдаём GigaChat Pro с чётким промптом: Клиент написал X. Вот 15 позиций. Выбери одну или верни null. Объясни выбор по атрибутам, а не по похожести строк.

Важно, жёсткий JSON Schema. Модель не может придумать новый SKU, только выбирает из списка. Если ничего не подошло, заявка идёт менеджеру.

Порог уверенности Самое интересное было не с моделью, а с порогом confidence. Разметили 1200 реальных заявок и получили такую картину:

0.95+ — 98.4% точности (71% заявок) 0.80–0.94 — 91.2% 0.60–0.79 — 73% ниже 0.60 — 41.5% Порог автоподтверждения поставили на 0.90. В итоге 76% позиций уходит автоматически, 20% — в полуавтомат, 4% — на ручной разбор.

Почему первый подход провалился Сначала попробовали просто эмбеддинги и топ-1 по близости. На синтетике было 78%, в проде упало до 61%. Модель не различала, что сечение 2.5 и 4 это два разных товара.

Пришлось явно прописать в промпте приоритеты: Сечение, количество жил и исполнение должны совпадать буквально. После этого точность прыгнула до 94%.

Что получилось в цифрах Время на позицию: 4–7 минут — 15 секунд (при высоком confidence) Доля заявок за 24 часа: 64% — 97% Ошибок с “привезли не то”: 11 в месяц — 2

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

Рабочая схема: эмбеддинги для грубой фильтрации + LLM для финального выбора + порог уверенности для разделения автомата и человека. И обязательно считайте метрики на реальных заявках, а не на синтетике.

ссылка на оригинал статьи https://habr.com/ru/articles/1057048/