Главная
remove check_box_outline_blank close

Опыт создания AI-консультанта (Часть -1)

2026-02-10

Опыт создания AI-консультанта: Путь от медленного Fine-tuning к быстрому RAG. Часть 1

В 2026 году идея создать собственного AI-ассистента уже не кажется научной фантастикой. Это становится необходимостью для бизнеса, который хочет оставаться конкурентоспособным. Представьте себе консультанта, который доступен 24/7, знает всё о вашем ассортименте, никогда не устает и мгновенно отвечает на самые каверзные вопросы клиентов. Именно такую задачу я поставил перед собой, решив создать умного ассистента для компании-производителя автозапчастей «ВФ-Авто».

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

Зачем это нужно в 2026 году? Преимущества AI-агента для бизнеса

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

  1. Мгновенная экспертиза. Клиенту не нужно ждать ответа менеджера. Он получает точную информацию о применяемости запчасти, ее характеристиках и аналогах здесь и сейчас.
  2. Разгрузка отдела продаж. Ассистент берет на себя рутинные вопросы, позволяя менеджерам сконцентрироваться на сложных сделках и работе с ключевыми клиентами.
  3. Круглосуточная поддержка. Ваш «лучший продавец» работает без перерывов и выходных, помогая клиентам из разных часовых поясов.
  4. Стандартизация знаний. Вся информация о товарах хранится в единой базе, исключая ошибки и «человеческий фактор», когда один менеджер знает больше другого.

Цель была ясна: создать не просто чат-бота, а настоящего цифрового эксперта. Мой первый инстинкт был — «научить» модель всему, что мы знаем.

Глава 1: Искушение Fine-tuning и холодный душ реальности

Логика казалась простой: если мы хотим, чтобы модель знала наш товар, нужно ее дообучить (fine-tune) на наших данных. Для экспериментов я использовал вполне доступное «железо»: видеокарту NVIDIA GeForce 3060 с 12 ГБ видеопамяти.

Попытка №1: Модель Qwen-1.5B

Я начал с относительно легковесной модели Qwen-1.5B. Процесс дообучения прошел на удивление гладко. Модель действительно «впитала» в себя данные о товарах. Но когда я попытался использовать её, меня ждало разочарование.

Проблема: катастрофически долгое время ответа.

Время генерации ответа доходило до 96 секунд. Можете представить себе клиента, который ждет ответа полторы минуты? Это неприемлемо.

При этом загрузка видеопамяти составляла всего около 5 ГБ. Казалось бы, есть огромный запас, но ни свободная память, ни тензорные ядра не спасали ситуацию. Скорость инференса (генерации ответа) была узким местом.

Попытка №2: Модель Qwen-3B

Я предположил, что проблема может быть в самой модели, и решил попробовать более «умную» и крупную версию — Qwen-3B. Качество ответов действительно выросло. Модель стала лучше понимать контекст и давать более точные рекомендации.

Но за это пришлось заплатить.

  • VRAM: Загрузка видеопамяти при старте подскочила до 9 ГБ, оставив совсем небольшой запас.
  • Скорость: Время ответа... практически не изменилось. Оно все так же колебалось в районе 80-90 секунд.

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

Глава 2: Поворот к RAG. Как заставить модель «подсматривать»

После неудач с fine-tuning я решил кардинально сменить стратегию и сфокусироваться на архитектуре RAG (Retrieval-Augmented Generation).

Идея RAG элегантна: вместо того чтобы заставлять модель «помнить» все данные, мы даем ей возможность «подсматривать» в базу знаний в реальном времени.

Процесс выглядит так:

  1. Пользователь задает вопрос (например, «нужна прокладка для двигателя КАМАЗ Евро-2»).
  2. Система не передает вопрос сразу модели. Сначала она ищет в специальной векторной базе данных (в моем случае — Qdrant) наиболее релевантные документы, описывающие нужные прокладки.
  3. Затем система формирует новый, расширенный запрос к LLM, который включает в себя и исходный вопрос пользователя, и найденные фрагменты из базы знаний.
  4. Большая языковая модель (LLM) получает этот контекст и генерирует ответ, основываясь на предоставленных ей фактах, а не на своей «памяти».

Этот подход обещал решить мои главные проблемы:

  • Скорость: Модели не нужно «напрягать» все свои знания, она работает с небольшим, релевантным фрагментом текста.
  • Актуальность: Чтобы обновить знания консультанта, достаточно обновить базу данных, а не переобучать всю модель.
  • Точность: Модель не «галлюцинирует», так как ее ответы жестко привязаны к найденным документам.

Глава 3: Подготовка данных — фундамент для RAG

«Мусор на входе — мусор на выходе». Это золотое правило работает и для LLM. Качество ответов AI-ассистента на 90% зависит от того, как мы подготовим для него базу знаний.

Шаг 1: Извлечение (Extraction)

Первым делом нужно выгрузить данные. У меня было два пути:

  1. Парсер: Написать скрипт, который будет обходить сайт и собирать информацию из разных полей (Характеристики, Применяемость, Марка). Это хороший вариант, если данные на сайте разбросаны по разным таблицам в базе данных.
  2. Прямая выгрузка: Выгрузить контент всех страниц напрямую из базы данных. Этот путь быстрее, но есть риск получить неполные или «грязные» данные.

Я выбрал первый путь. Вот пример «сырых» данных, которые я получил для одного товара:

{
  "url": "https://vfavto.ru/navigacziya/proizvoditeli/kamaz/kolczo-upl.-7405-1303172.html",
  "title": "Кольцо упл. системы охлаждения ( 172 )",
  "normalized_title": "кольцо уплотнительное системы охлаждения",
  "description": "Уплотнительное кольцо с артикулом 7405-1303172— это уплотнительный элемент для соединений в системе охлаждения двигателей КАМАЗ.",
  "article": "7405-1303172",
  "price_full_string": "Цена по запросу",
  "characteristics": {
    "Артикул": "7405-1303172",
    "Тип": "кольцо уплотнительное системы охлаждения",
    "Материал": "Силиконовый компаунд (термостойкий эластомер)"
  },
  "applicability": {
    "Автомобили": "КАМАЗ",
    "Двигатели": "Двигатели КАМАЗ",
    "Узел": "Система охлаждения"
  }
}

Шаг 2: Нормализация и обогащение

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

replacements = {
    "упл.": "уплотнительное", "уплотнит.": "уплотнительное",
    "рем-кт": "ремкомплект",
    "дв.": "двигатель",
    "гбц": "головки блока цилиндров",
    "пркл.": "прокладка",
}
# ... и так далее

Далее я написал конвертер, который превращает плоскую структуру в обогащенный «цифровой паспорт» товара. Я добавил туда новые поля: brands, product_type, search_keywords и, самое главное, embedding_text — специальное текстовое поле, которое будет превращено в вектор для поиска.

Вот что получилось после обработки:

{
  "id": 85431,
  "url": "https://vfavto.ru/navigacziya/proizvoditeli/kamaz/kolczo-upl.-7405-1303172.html",
  "title": "Кольцо упл. системы охлаждения ( 172 )",
  "normalized_title": "кольцо уплотнительное системы охлаждения",
  "description": "Уплотнительное кольцо с артикулом 7405-1303172— это уплотнительный элемент для соединений в системе охлаждения двигателей КАМАЗ.",
  "brands": ["МАЗ", "КАМАЗ"],
  "product_type": "Кольцо",
  "search_keywords": [
    "кольцо уплотнительное системы охлаждения",
    "7405-1303172",
    "МАЗ",
    "КАМАЗ"
  ],
  "embedding_text": "Товар: Кольцо упл. системы охлаждения ( 172 ) | Описание: Уплотнительное кольцо с артикулом 7405-1303172— это уплотнительный элемент для соединений в системе охлаждения двигателей КАМАЗ. | Марки: МАЗ, КАМАЗ | Характеристики: Артикул: 7405-1303172; Тип: кольцо уплотнительное системы охлаждения; Материал: Силиконовый компаунд (термостойкий эластомер) | Применяемость: Автомобили: КАМАЗ; Двигатели: Двигатели КАМАЗ; Узел: Система охлаждения"
}

Для приведения разных написаний брендов и типов товаров к единому стандарту я использовал словари-мэппинги. Я назвал этот процесс «слова к слову» — не судите строго, я небольшой выдумщик названий :)

# Приводим 'газель', 'волга' к 'ГАЗ'
self.brand_mapping = {
    'газ': 'ГАЗ', 'уаз': 'УАЗ', 'волга': 'ГАЗ',
    'газель': 'ГАЗ', 'камаз': 'КАМАЗ', 'маз': 'МАЗ',
}

# Приводим 'рукав' и 'патрубок' к одному типу
self.product_type_mapping = {
    'прокладка': 'Прокладка', 'кольцо': 'Кольцо',
    'рукав': 'Рукав/Патрубок', 'патрубок': 'Рукав/Патрубок',
}

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

Продолжение следует...

arrow_back Назад к списку заметок
home integration_instructions description security design_services person contacts
dark_mode