Как я написала программу для автоматического сопоставления номенклатуры в 1С. Мои полгода проб и ошибок

от автора

Предыстория

Давайте сразу оговорюсь, дабы вы не судили меня строго. Я не программист, а скорее маркетолог с навыками программирования и некоторыми знаниями в IT. Но речь в этой статье пойдёт далеко не о маркетинге, а о программе, которую мне довелось разработать. Для меня это было внезапно;‑)

Летом 2025 года мне мой муж начал рассказывать о проблемах своей компании. У них просто ужасно много времени уходило на внесение в 1С заявок клиентов. Настолько ужасно, что для этого держали 8!!! офис‑менеджеров, при общем штате компании человек в 40. Это чтобы вы осознали масштаб проблемы.

Я хлопала глазами и предлагала воспользоваться стандартным функционалом сопоставления номенклатуры в 1С. Он крутил у виска и говорил, что это не сработает: клиенты любили очень причудливо описывать требуемые позиции. Плюс, ладно сама позиция, так и заявка была оформлена вообще как угодно. И вообще не соответствовала их номенклатуре. Офис‑менеджер и то еле разбирал, что там клиент написал. О какой 1С речь?

Кстати, еще маленькое вводное. У компании было около 8000 позиций номенклатуры. Причём, написание части позиций могло различаться одним символом.

Первоначальный вариант программы

Мне стало интересно, а как вообще такие проблемы решаются. Тем более, я была в декрете со второй малышкой, и очень хотелось заняться хоть чем‑то, кроме детей. Я описала Клоду проблему. Он сказал, что всё элементарно (у нейросетей всё легко и просто, а потом ты месяцами это «просто» дорабатываешь). Щас напишем на Питоне программу. Там как раз есть стандартная библиотека для неточного сопоставления. FuzzyWuzzy называется. Плюс ещё машинное обучение прикрутим, и всё вообще взлетит!

К слову, в Питоне я вообще не шарю. Так что поверила на слово. А Клод, тем временем, накатал мне прототип. И да! Он работал! Не то чтобы он сопоставлял…. Но он как‑то работал. Я решила, что основа есть, дальше будем на ней ваять шедевр!

Многопользовательский режим и веб‑интерфейс

И началось… Вместо того, чтобы настраивать логику, я попёрлась в веб‑интерфейс и многопользовательский режим. А ещё придумала архитектуру на докере: для меня важно было быстро разворачивать программу на любом сервере. Я ещё не знала, как будем устанавливать программу компании, для которой её писала. И уже строила грандиозные планы насчёт следующих. Хотя, говоря по правде, та компания ещё не стала моим заказчиком (но я буду её назвать заказчиком далее по тексту, дабы избежать путаницы). Это я просто взяла задачу и решила попробовать что‑то для неё сделать. И в случае неуспеха я бы просто потратила время.

Главный экран новой программы

Главный экран новой программы

Короче, что получилось. Три контейнера: frontend на React, backend на FastAPI (Python) и БД PostgreSQL. Всё было симпатичненько. Запомненные машинным обучением позиции отлично сопоставлялись. Не запомненные — в 95% нет.

Вот как выглядят контейнеры

Вот как выглядят контейнеры

Это меня удручало, но я не унывала. Компания заказчика занималась инструментами (свёрла, метчики, фрезы и др.), и такие вещи, как диаметр, имели весьма серьезное значение. Ну я и сделала фильтры по диаметру. Правда, ещё раз напомню, когда я говорю «я» — это значит «Клод Код по моему промпту». Стало лучше. Но не намного. Может, процентов на 5.

Я задумалась, что делать дальше. А дальше муж сказал: такое, наверное, только нейросеть какая сможет сматчить. Ага. Точно нейросеть…

Нейросети и embeddings

Сначала я, как не очень умный и прошаренный человек, пыталась установить себе на компьютер локальную нейросеть по совету Клода (у него вообще очень странные советы бывают, пока ты сам не придумаешь, как реально надо, лучше его не слушать). Короче, нейросеть в Докер (а Клод сказал, что будем грузить её туда) даже не закачалась. Я расстроилась и посмотрела в сторону облачных решений. Так как я не была уверена в наличии vpn у заказчика и вообще будущности взаимодействия с иностранными нейросетями — я начала прикручивать Яндекс GPT.

Клод оптимистично заявил, что мне только функционала embeddings хватит. Я ему, как всегда, поверила. Оказалось — нет. Не хватит. Качество сопоставления практически не улучшилось. Зато, как пострадала скорость! Дальше уже предлагала я. Решила: ну ок, пусть эмбеддингс будет, но к нему явно нужно еще уровень добавить. И добавила выбор из 10 лучших по соответствию кандидатов Яндекс GPT через промпт. Хотелось бы, конечно, кидать Яндексу все 8000 позиций, но я понимала, что это бред, который сожрёт кучу денег и времени.

Загрузка заказа клиентов

Загрузка заказа клиентов

После нововведения стало лучше. Если бы не 2 важных НО:

  1. Скорость просела так, что делала мою сопоставлялку бесполезной. Заказ из 100 позиций сопоставлялся 20 минут. Офис‑менеджер работал примерно с той же скоростью, но выдавал лучшие результаты, по итогу ;‑)

  2. Всё равно около 70% позиций не сопоставлялось. По сравнению с тем, что было раньше — это был прорыв. Но явно недостаточный.

Причем, проблема была в 2-х местах:

  1. После эмбеддингс далеко не всегда нужная позиция оказывалась в ТОП-10. Точнее, она чаще не оказывалась, чем оказывалась.

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

Замена нейросети на GPT и разбор входных данных

Как я уже писала выше, я начала разочаровываться и в Яндексе, и в эмбеддингс. Больше всего меня раздражали последние, потому что жрали просто уйму времени. И я решила их убрать. Оставила стандартное сопоставление, реализованное на Питоне до этого. И из него уже отправляла 10 позиций нейросети.

С нейросетью я тоже переиграла. Выбрала ChatGPT. Из всех вариантов она была, на мой не слишком прошаренный взгляд, лучшая по цене и качеству сопоставления. И да, действительно, стало лучше. Меньше глупых несоответствий, больше правильных ответов. Разумеется, всё время тестирования я еще и промпт увеличивала в объёме. Но это уже детали. Теперь сопоставлялось, может, 40% позиций.

И был ещё один важный момент. На входе позиции разбирались через Питон. И если формат был нестандартный (их было великое множество), то уже на входе всё ломалось и сопоставление не получалось. Тогда мне пришла в голову гениальная идея отдать разбор позиций тому же GPT! Так родился второй промпт для разбора позиций.

А вот и мои промпты

А вот и мои промпты

Но, несмотря на все эти улучшения, система работала явно так себе и показывать её заказчику не имело смысла.

Внедрение фильтрации

Я обсуждала эту проблему с мужем, и он мне твердил одно и то же. Типа, ты разложи позиции по группам, как у нас в 1С, и из них уже ищи. Ну я и попробовала. Загрузила Excel с позициями по группам, как из их 1С. И попробовала сопоставлять так. Где‑то это действительно работало. Но в большинстве случаев — нет. Почему? Потому что в одной группе могли лежать совсем разные позиции. В некоторых группах позиций было 1000 или больше. Больше всего меня впечатлила группа «Прочее», где также было около 1000 позиций, которые никто не удосужился категоризировать.

Я пробовала все это категоризировать сама. Ну программно, то есть. Цепляться за общие слова в группе, например. Но всё было тщетно. Может, какой‑то эффект это давало, но правильной категоризации и, как следствие, корректного сопоставления добиться не удавалось.

И тут мне пришла в голову интересная мысль. А если не категоризация, а фильтрация? Берём список слов фильтров и по ним фильтруем номенклатуру! Например, сверло, метчик, плашка и так далее? Отфильтруется именно то, что нужно! Правда 2000 свёрл — это слишком… Нужно что‑то ещё. И тогда я решила фильтровать по характеристикам. Например, по маркам стали, по особенностям изделий, типа «глухой», «длинный» и так далее. Плюс оставалась изначально написанная фильтрация по диаметрам. Таким образом, у меня иногда на выходе после фильтрации могла быть и одна позиция! Но иногда, правда, и 200 получалось.

Вот и моя фильтрация любимая

Вот и моя фильтрация любимая

Но в целом, качество сопоставления выросло в разы! Теперь сопоставлялось около 80% позиций! Это был настоящий прорыв. И я понимала, что тестируя в дальнейшем, совершенствуя промпты и фильтры, я могу сопоставлять почти 100% позиций.

Дополнительные доработки

Вот что я ещё сделала для увеличения удобства использования и улучшения сопоставления:

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

  2. Добавила в характеристики асимметричную фильтрацию. При стандартной фильтрации, если позиция клиента не содержит характеристики «глухой», значит, все варианты с «глухой» уходят. При асимметричной, фильтрация работает только если позиция клиента содержит «глухой», тогда остаются только варианты с «глухой». А если «глухой» в позиции клиента нет, то фильтрация по этому слову не запускается.

  3. Ввела обогащение дополнительными описаниями позиций номенклатуры. Например, добавила марки стали, где они подразумевались, но не были указаны в названии позиции.

  4. Добавила возможность исключения некоторых позиций из сопоставления.

  5. Сделала комментарии для GPT и возможность отправки на повторное сопоставление с новым комментарием.

  6. Ввела загрузку артикулов и реализовала поиск по артикулу.

  7. Реализовала хранение истории сопоставлений и сбор данных для обучения gpt (честно, даже не запускали, вроде, итак хорошо работает).

Обогащение описаний

Обогащение описаний

И самое неожиданное для меня самой: я вернула эмбеддинги. Если при фильтрации оставалось больше 30 позиций, то позиция, отправленная на сопоставление, получала эмбеддинг и сопоставлялась по нему (позиции номенклатуры поставщика получали эмбеддинги при загрузке номенклатуры и хранились в кэше). Так как в этот раз использовался кэш, и эмбеддинги получались только на небольшую часть позиций и сопоставлялись не с 8 тысячами, а, скажем, со 100 позициями, то скорость сопоставления особо не пострадала, а качество улучшилось.

Страница с результатами сопоставления

Страница с результатами сопоставления

В общем и целом моя схема сопоставления выглядела так: разбираем заказ с помощью GPT → Если сохранено в обучении, название совпадает до знака или артикулы 100% совпадают → сопоставляем → Иначе, фильтруем по категориям и характеристикам → если остаётся более 30 позиций, с помощью эмбеддингов выделяем ТОП-10 → если менее 30, то всё, что осталось, отправляем GPT для выбора — GPT делает выбор.

Схема сопоставления номенклатуры

Схема сопоставления номенклатуры

И знаете. Ну 95% позиций уже точно сопоставляется. Заказчик программу принял, заплатил денежку. Сотрудники заказчика хлопают в ладоши и активно сопоставляют позиции. Потом они одним кликом переносятся в заказ 1С. Кстати, офис‑менеджеров не уволили. Просто загрузили другими задачами. Так что все счастливы :‑) И я тоже. Ведь я сделала то, о чём раньше и помыслить не могла. Спасибо Клод Коду. Кстати, за время разработки он значительно поумнел. И, думаю, если бы я взялась за разработку сейчас, то завершила бы её значительно быстрее. А так у меня она вяло тянулась полгода по паре часов в день, а то и с месяцами простоя.

На этом всё. Надеюсь, вам было интересно. А может, даже и полезно;‑)

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