ИИ-сервис извлечения характеристик товара из наименования

Заказчик: Часть крупного проекта (ИИ-бот оценки среднего чека)
Стек: Python, SpaCy (NER), qwen3-4b, Pydantic Structured Output, FastAPI, Docker; обучение на Ryzen 3600X + NVIDIA RTX 3080Ti

Задача

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

Результат

SpaCy NER извлекает тип, модель, бренд и артикул из наименования; 20 000 позиций обрабатываются менее чем за 1 минуту. Сервис автодообучается на новом прайсе и работает локально.

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

В чём была проблема

Одинаковые по смыслу товары у разных поставщиков лежали в разных группах, а часто вообще не по теме. Прайсы меняются часто, поставщиков много, а прогонять 20 тысяч позиций через большую LLM — долго. Небольшая локальная модель qwen3-4b с задачей группировки справляется, но для потока в 20 тысяч строк нужно было что-то быстрое.

Решение: SpaCy вместо LLM на потоке

Я взял модель SpaCy — она работает намного быстрее и сейчас 20 тысяч позиций обрабатывает меньше чем за минуту. А LLM (qwen3-4b) со схемой Structured Output использовал не на потоке, а один раз — чтобы подготовить размеченный датасет для обучения SpaCy. Схема разметки на Pydantic выглядела так:

class LabelSpan(BaseModel):
    label: Literal["PRODUCT_TYPE"] = Field(description="Категория характеристики")
    text: str = Field(description="Фрагмент исходного текста")
    start: int = Field(description="Начальный индекс фрагмента")
    end: int = Field(description="Конечный индекс фрагмента")

class ProductDataExtraction(BaseModel):
    text: str = Field(description="Исходный текст")
    labels: List[LabelSpan] = Field(description="Извлечённые характеристики")

В этом датасете размечается только «Категория», но по той же схеме можно обучить извлекать любые характеристики. Например, из товара «Пресс гидравлический ПГРс-300 КВТ 49627» получаем:

{
  "type": "пресс гидравлический",
  "model": "ПГРс-300",
  "brand": "КВТ",
  "article": "49627"
}

Эти данные удобно использовать в любой системе. В 1С ими можно заполнить характеристики товара, предварительно выполнив нормализацию.

Важный нюанс обучения

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

Как устроен сервис

На готовом датасете обучается модель SpaCy, доступ к ней даётся через FastAPI. Отдельные блоки принимают новый прайс и сами выполняют разметку, подготовку датасета и обучение — то есть модель просто дообучать на новых данных. Изначально сервис сделан под локальные модели, но легко переключается на любую облачную LLM. Подготовка датасета и обучение шли на Ryzen 3600X + RTX 3080Ti примерно за день, дообучение — гораздо быстрее. Всё собрано под Docker, поэтому разворачивается на любой системе одной командой. Другие наши ИИ-проекты собраны в разделе Кейсы.

Хотите так же применять ИИ к своей номенклатуре

Извлечение характеристик, нормализация и обогащение карточек товара через ИИ — это то, чем мы занимаемся на курсе по ChatGPT и нейросетям для 1С. Там же — Structured Output, локальные модели и интеграция с базой.

Частые вопросы

Нужен похожий проект?

Опишите задачу — оценю сроки и стоимость.