Как получать эффект от ИИ, когда нет железа

от автора

Вы уверены, что для внедрения корпоративного ИИ в закрытом контуре нужны суперкомпьютеры? Мы решили проверить и добиться вменяемого качества от крошечной модели в максимально жестких условиях:

  • CPU вместо GPU;

  • закрытый контур.

Кейс – научить крошечную модель LLM отвечать на вопросы по программе газификации РФ.

В статье: пошаговый разбор, код LLLaMBA для автоматизации бенчмарка и готовые конфиги. Повторите эксперимент на своих данных!

Локальные LLM выглядят как простое и дешевое решение, однако достижение высокого качества ответов от таких моделей является настоящей инженерной задачей

Локальные LLM выглядят как простое и дешевое решение, однако достижение высокого качества ответов от таких моделей является настоящей инженерной задачей

Вступление

Корпоративный сегмент РФ оказался в условиях дефицита мощных вычислительных ресурсов – официальные поставки серверных видеокарт Nvidia A100/H100/H200 запрещены санкциями с 2022 года. Несмотря на это, спрос на ИИ растёт, в связи с чем мы видим закономерный рост продаж видеокарт игровых моделей в 2025 году (+60% за 9 месяцев, лидеры – RTX 3050 и 4060). Компании вынуждены использовать их как замену серверным решениям, теряя в производительности и масштабируемости. Эта реальность делает небольшие и эффективные LLM не просто предпочтительным, а практически единственным вариантом для корпоративного внедрения ИИ в России.

Локальные LLM снимают вопросы ИБ и экономят ресурсы, но проигрывают в качестве: меньше фактов в весах, слабее следование инструкциям, выше шанс галлюцинаций. Как я уже писал в предыдущей статье (🌐 ссылка ), продукт с LLM – это всегда «вероятность решения конкретной бизнес-задачи, которая не равна 100%».

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

Методика эксперимента

Инструменты

Для подготовки данного материала был создан вспомогательный инструмент «LLLaMBA» (Local LLM Benchmark Automat). Исходный код инструмента доступен по ссылке (🌐 ссылка на репозиторий), для повторения эксперимента на ваших данных.

Для инференса локальной LLM была выбрана библиотека ollama. Для обращения к «судье» при реализации LLM-as-a-Judge в эксперименте использовалось OpenAI-совместимое API, модель Qwen3-Max.

В качестве подопытного кролика была выбрала qwen3:0.6b. Причины:

  • Модель генерирует ответ за короткое время, даже на CPU (от 2 сек).

  • На модели малого размера рост метрик виден нагляднее.

Процесс эксперимента

  • Готовим перечень вопросов, релевантный контекст, правильные ответы – в виде .xlsx-файла.

  • Пишем конфиг эксперимента в виде .yaml-файла. Примеры есть в репозитории, а также в тексте статьи.

  • Далее запускаем LLLaMBA, которая делает следующее:

    • Прогоняет конфиг по заранее сформированному пайплайну.

    • Подаёт промт на вход тестируемой модели, получает ответ.

    • Ответ тестируемой модели + правильный ответ подаёт судье, получает числовую оценку от 1 до 100 баллов.

    • Логирует входную и выходную информацию.

  • Оцениваем метрику, возвращаемся на шаг 2 и повторяем эксперимент до достижения желаемого результата.

Предупреждение

При проведении эксперимента учитывайте вероятностную природу ответа LLM:

  • Текст ответа тестируемой LLM от эксперимента к эксперименту может меняться при одинаковых входных данных.

  • Числовой балл LLM-судьи от эксперимента к эксперименту может меняться при одинаковых входных данных.

В связи с этим:

  • Всегда запускайте серию экспериментов (рекомендую 5 раз и более).

  • Не доверяйте росту или падению метрик без самостоятельной проверки ответов (Human-as-a-Judge 👍).

Легенда

Представим, что мы хотим разработать информационную систему, которая бы помогала получать ответы на вопросы об одном из наиболее масштабных инфраструктурных проектов в сфере энергетики – программе газификации Российской Федерации, реализуемой ПАО «Газпром».

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

  • Должен ли я платить за подготовку договора о подключении газа?

  • Газовая компания требует от меня какие-то дополнительные справки, которых нет в списке. Правомерно ли это?

  • Куда мне нужно обратиться, чтобы подать заявку на подключение газа к дому?

  • Может ли газовая компания отказать мне в заключении договора, если у них «нет мест» или «сейчас не занимаемся подключениями»?

  • Я хочу открыть небольшую пекарню на первом этаже своего дома. Смогу ли я подключиться бесплатно по программе догазификации?

Ответы на эти вопросы есть в Постановлении Правительства РФ №1547 от 13.09.2021 «Об утверждении Правил подключения (технологического присоединения) газоиспользующего оборудования и объектов капитального строительства к сетям газораспределения». Итоговый датасет приведён в репозитории по ссылке выше.

Экспериментируем

Предел возможностей ⬆

В начале необходимо понять максимальный уровень, на который способна модель, чтобы не строить лишних иллюзий. Для этого прогоним её через cheat-pipeline, буквально добавив в промт правильный ответ, а также установим минимальные значения температуры, top_p и top_k, чтобы модель не отклонялась от инструкций. Настройки конфига будут приведены под спойлером. Следом за спойлером — команда на запуск бэнчмарка и итоговый результат.

Настройки конфига
pipeline: cheatsystem_prompt: "" # prompt_template: "Вопрос: {question}\nОтвет: {ground_truth}\nПовтори ответ."parameters:  temperature: 0.1  # низкая температура для более детерминированного ответа  top_p: 0.1  top_k: 10num_repetitions: 5
>>> uv run main.py --config configs/cheat.yaml>>> ...>>> Итог по серии: медианный балл 100.0, разброс от 100.0 до 100.0

Результат отличный – стабильные 100 баллов, разброс отсутствует. При передаче в промт на 100% корректной информации даже такая маленькая модель стабильно генерирует идеальный результат без смысловых искажений. Сюрреалистичная иллюстрация того, насколько для LLM важен релевантный контекст.

Дело за малым – добиться такого же качества, но без передачи в модель правильного ответа.

Базовый минимум ⬇

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

Настройки конфига
pipeline: baselinesystem_prompt: ""prompt_template: "Ответь на вопрос: {question}"parameters:  temperature: 0.7  top_p: 0.9  top_k: 40  enable_thinking: false # отключает thinking-режим для qwen, добавляя /no_think в промтnum_repetitions: 5
>>> uv run main.py --config configs/baseline.yaml>>> ...>>> Итог по серии: медианный балл 20.0, разброс от 10.0 до 22.5

Получаем медианную оценку в 20 баллов, а на самой плохой серии – 10 баллов. Такой уровень качества нас не устраивает.

Рассуждения 💭

При определении нижнего порога я отключил thinking-mode. Для моделей Qwen это, конечно же, не очень правильно. Включим его обратно и посмотрим, как это повлияет на метрики.

Настройки конфига
pipeline: baselinesystem_prompt: ""prompt_template: "Ответь на вопрос: {question}"parameters:  temperature: 0.7  top_p: 0.9  top_k: 40  enable_thinking: true # включили reasoning, остальное без измененийnum_repetitions: 5
>>> uv run main.py --config configs/baseline_reasoning.yaml>>> ...>>> Итог по серии: медианный балл 20.0, разброс от 20.0 до 27.5

Результат – те же 20 баллов, на отдельных тестах – 27,5 баллов. В данном случае режим рассуждений не дал никакого прироста к медианному баллу, лишь немного увеличив способность к угадыванию правильных смыслов.

Жесткие рамки 🥶

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

Настройки конфига
pipeline: baselinesystem_prompt: ""prompt_template: "Ответь на вопрос: {question}"parameters:  temperature: 0.1 # уменьшаем  top_p: 0.1 # уменьшаем  top_k: 10 # уменьшаем  enable_thinking: truenum_repetitions: 5
>>> uv run main.py --config configs/baseline_reasoning_strict.yaml>>> ...>>> Итог по серии: медианный балл 20.0, разброс от 20.0 до 20.0

Разброс стал меньше, но итоговая метрика качества не изменилась, те же 20 баллов. Если раньше модель иногда угадывала правильные смыслы, то теперь такой возможности у неё нет. Низкие temperature, top_p, top_k не добавляют модели знаний – они лишь фиксируют стратегию выбора токенов.

Ролевые игры 🎭

Широко используется подход с заданием модели конкретной роли. Добавим эту информацию в системный промт, дав модели немного контекста о предметной области.

Настройки конфига
pipeline: baselinesystem_prompt: "Ты - специалист по вопросам подключения и технологического присоединения газоиспользующего оборудования и объектов капитального строительства в Российской Федерации"prompt_template: "Ответь на вопрос: {question}"parameters:  temperature: 0.7  top_p: 0.9  top_k: 40  enable_thinking: truenum_repetitions: 5
>>> uv run main.py --config configs/baseline_role.yaml>>> ...>>> Итог по серии: медианный балл 20.0, разброс от 17.5 до 22.5

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

Вводный инструктаж 👷‍♂️

Добавим в системный промт больше информации о предметной области. Для этого возьмём пункт Постановления Правительства РФ, в котором изложены основные понятия документа, и оформим из него понятный для модели .md-файл:

Ты – специалист по вопросам подключения и технологического присоединения газоиспользующего оборудования и объектов капитального строительства в Российской ФедерацииТвоя задача — отвечать на вопросы граждан о порядке подключения газоиспользующего оборудования к сетям газораспределения.В своей работе ты руководствуешься следующими терминами и понятиями:- "**государственные и инвестиционные программы**" - предусматривающие строительство, реконструкцию перспективных сетей...и так далее весь пункт с понятиями из ПП РФ без изменений.

Итоговый .md файл вышел на 4276 токенов, т.е. примерно 12% контекстного окна. Передаём этот файл в системный промт и запускаем эксперимент.

Настройки конфига
pipeline: baselinesystem_prompt_file: "gas_domain.md" # путь до файла с промтом, в котором записан вводный инструктажprompt_template: "Ответь на вопрос: {question}"parameters:  temperature: 0.7  top_p: 0.9  top_k: 40  enable_thinking: truenum_repetitions: 5
>>> uv run main.py --config configs/baseline_domain.yaml>>> ...>>> Итог по серии: медианный балл 30.0, разброс от 22.5 до 30.0

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

Приведу пример вопроса и некорректного ответа из вышеуказанного теста:

Вопрос №10: «Я хочу открыть небольшую пекарню на первом этаже своего дома. Смогу ли я подключиться бесплатно по программе догазификации?»

Ответ модели: «Да, вы можете подключиться к программе «догазификации» по условиям первой категории, если подключение будет на территории сельской местности (вне границ городов и поселков) и протяженность сети до точки подключения не превышает 500 метров».

На первый взгляд ответ модели выглядит неплохо. В ответе используются специфичные термины и корректно выстроенные предложения. К сожалению, по смыслу ответ неверный. Использование подходов, основанных только на добавление в промт модели доменных терминов, в продуктивной среде – опасно, так как пользователи могут быть введены в заблуждение.

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

Взлёт на RAG-ете 🚀

Выполним эмуляцию RAG-ретривера – для каждого вопроса вручную дадим модели релевантный пункт Постановления Правительства. Текст пункта оставим без изменений.

В рамках статьи мы формируем контекст вручную, чтобы изолировать влияние его качества на ответ модели. В ИС «АФИДА», которую разрабатывает наша команда, этот процесс автоматизирован: документы индексируются в векторной БД, релевантный текст извлекается по семантическому сходству и подаётся в модель.

Ниже пример комбинации вопроса и текста из источника:

Вопрос: Должен ли я платить за подготовку договора о подключении газа?

Контекст для модели: «# Постановление Правительства РФ «Об утверждении Правил подключения (технологического присоединения) газоиспользующего оборудования и объектов капитального строительства к сетям газораспределения». ## Раздел II «О заключении договоров о подключении». ### Пункт 50. Подготовка и направление исполнителем заявителю проекта договора о подключении осуществляются без взимания платы.»

Настройки конфига
name: rag_basepipeline: ragsystem_prompt: ""prompt_template: "Ответь на вопрос, используя следующий контекст:\n{context}\nВопрос: {question}"parameters:  temperature: 0.7  top_p: 0.9  top_k: 40  enable_thinking: truenum_repetitions: 5
>>> uv run main.py --config configs/rag_base.yaml>>> ...>>> Итог по серии: медианный балл 72.5, разброс от 45.0 до 85.0

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

Ниже пример хорошего ответа с метрикой в 90 баллов:

Вопрос №6: Куда мне нужно обратиться, чтобы подать заявку на подключение газа к дому?

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

Для всесторонней оценки приведу пример плохого ответа с метрикой в 10 баллов:

Вопрос №8: С кем я буду заключать договор на подключение газа — с одной организацией или с несколькими?

Ответ модели: С одной организацией.

Коротко и по существу, но не вполне правильно. В исходном тексте есть нюансы (в общем случае договор заключается с несколькими организациями, и только в одном определенном случае – с одной). Модель не извлекла эти нюансы из контекста и поэтому ответила на вопрос не полностью. Значит, нам есть над чем поработать в следующей части статьи.

Промежуточные итоги

Зафиксируем на графике, что мы попробовали и к каким результатам это привело:

Количество баллов, полученных в результате экспериментов, в зависимости от использованных приёмов

Количество баллов, полученных в результате экспериментов, в зависимости от использованных приёмов

В табличном виде:

№ этапа

Наименование этапа

Минимальный балл

Максимальный балл

Медиана

1

Определение верхней границы

100

100

100

2

Определение нижней границы

10

22,5

20

3

Включение режима рассуждений (reasoning)

20

27,5

20

4

Уменьшение температуры, top_p и top_k

20

20

20

5

Добавление роли

17,5

22,5

20

6

Добавление доменной области

22,5

30

30

7

Добавление релевантного контекста

45

85

75,5

❌ Наглядно видно, что приемы, связанные с настройкой параметров инференса (reasoning, temperature, top_p, top_k, роль), дают лишь незначительные улучшения на некоторых экспериментах. В среднем, они не оказывают влияния на правильность ответа модели. Такие приемы можно использовать лишь для стабилизации результатов.

✅ Напротив, приемы, предоставляющие модели конкретный контекст, помогающий ответу на конкретный вопрос, оказывают значительное положительное влияние. Чем лучше контекст очищен от лишней информации и подходит по смыслу к вопросу, тем выше прирост метрик (вплоть до максимального количества баллов, даже на самых маленьких моделях).

В данной статье мы попробовали простые приёмы. В практике работы с локальными LLM есть гораздо более сложные методики. Если вам интересна тематика работы с моделями, которые можно недорого развернуть on-premise и использовать для решения внутрикорпоративных задач, пожалуйста, поставьте статье «плюс» или напишите про ваш интерес в комментариях. Так мы поймём, что эта тема востребована и быстрее подготовим вторую часть статьи.

Решение задач бизнеса

Если в вашей организации:

  • люди тратят дни, чтобы собрать информацию из документов разных отделов;

  • каждый хранит всё самое ценное локально, потому что искать на общих ресурсах – долго;

  • не понятно, как подружить искусственный интеллект с вашими документами;

  • требуется современное отечественное решение для работы с хаосом документации;

Пожалуйста, напишите нам на afida@gazpromcps.ru. Мы поможем 🤝

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