Мечта и реальность
Клиент пришел с простой задачей: "Надо автоматически проставить категории, подкатегории и атрибуты для 10,000 товаров из CSV-файла". Звучит как идеальный кандидат для промпт-инжиниринга, правда? Один красивый промпт, запустил - и через час получил готовый датасет.
На деле получилось три недели боли, 47 итераций отладки и осознание простой истины: промпт-инжиниринг в его классическом понимании - это тупик для сложных задач.
Если ваш промпт длиннее экрана - вы уже проиграли. Сложность не масштабируется линейно с длиной инструкции.
Первая попытка: монстр-промпт
Начали с логичного подхода: собрали все требования в один мега-промпт. Примерно 1500 слов инструкций, 50 примеров форматов, правила исключений, иерархию категорий - весь накопленный экспертный опыт в одном месте.
# Вот как выглядела первая версия
prompt = """
Ты - эксперт по классификации товаров для маркетплейса.
Твои задачи:
1. Определить основную категорию из списка: Электроника, Одежда, Дом, Красота, Спорт
2. Определить подкатегорию (например, для Электроника: Смартфоны, Ноутбуки, Наушники)
3. Извлечь бренд из названия
4. Определить цвет из описания
5. Выделить материал для одежды и домашних товаров
6. Определить размерную сетку
7. Проверить соответствие возраста
8. ... и еще 15 пунктов
Формат вывода: строго JSON с полями category, subcategory, brand, color, material, size, age_group, ...
Примеры правильных ответов:
- "iPhone 15 Pro Max 256GB черный" -> {"category": "Электроника", "subcategory": "Смартфоны", ...}
- "Джинсы Levi's 501 синие" -> {"category": "Одежда", "subcategory": "Джинсы", ...}
Правила:
- Если бренд не указан, оставляй поле пустым
- Если цвет не указан, анализируй описание
- Если есть противоречия, используй приоритет правил...
"""Результат? Точность 62%. Модель регулярно путала категории, пропускала атрибуты, игнорировала исключения. Хуже того - ошибки были непредсказуемыми. Один и тот же товар в разных запусках получал разную классификацию.
Почему это не работает
Разберем фундаментальные проблемы подхода "один промпт на все":
- Когнитивная перегрузка: LLM пытается держать в "голове" сразу 20+ правил и 50 примеров. Что-то обязательно выпадет
- Конфликт приоритетов: Когда правила противоречат друг другу, модель выбирает случайный вариант
- Невозможность отладки: Непонятно, какое именно правило сломалось. Переписываешь весь промпт из-за ошибки в одном пункте
- Дрейф контекста: На 1000-м товаре модель "забывает" правила с начала промпта
Кстати, похожая проблема была в статье про виртуальную примерку - там тоже пытались упаковать всю логику в один промпт и получили хаос.
Решение: разбиваем на атомарные шаги
Вместо одного монстра-промпта создали конвейер из 27 микропромптов. Каждый решает одну конкретную задачу:
1Шаг 1: Очистка и нормализация
Первый агент получает сырое название товара и приводит его к стандартному виду:
clean_prompt = """
Приведи название товара к стандартному виду:
1. Удали лишние пробелы
2. Приведи регистр (первая буква каждого слова заглавная)
3. Удали дублирующиеся слова
4. Исправь очевидные опечатки (iphone -> iPhone)
Примеры:
- "iphone 15 pro ЧЕРНЫЙ 256гб" -> "iPhone 15 Pro Черный 256 ГБ"
- "джинсы LEVIS джинсы 501" -> "Джинсы Levi's 501"
Вход: {product_name}
Выход: только очищенное название
"""2Шаг 2: Определение категории
Второй агент - только категория. Никаких атрибутов, только 5 возможных вариантов:
category_prompt = """
Определи основную категорию товара:
- Электроника
- Одежда
- Дом
- Красота
- Спорт
Правила:
1. Если товар содержит слова: телефон, смартфон, ноутбук, наушники -> Электроника
2. Если содержит: футболка, джинсы, платье, обувь -> Одежда
3. ... и так далее
Вход: {cleaned_name}
Выход: только название категории
"""И так далее. Отдельный агент для брендов, отдельный для цветов, отдельный для размеров. Каждый промпт - максимум 10 строк.
Этот подход напоминает принципы из статьи про ИИ как младшего коллегу. Не давайте стажеру сложную многозадачность - разбейте работу на простые шаги.
Архитектура конвейера
Вот как выглядит финальная система:
| Этап | Агентов | Точность | Время на товар |
|---|---|---|---|
| Предобработка | 3 агента | 99.8% | 0.2 сек |
| Классификация | 5 агентов | 98.5% | 1.1 сек |
| Атрибуция | 12 агентов | 97.2% | 2.3 сек |
| Валидация | 4 агента | 99.1% | 0.8 сек |
| Постобработка | 3 агента | 99.9% | 0.3 сек |
Общая точность: 94.7% против изначальных 62%. Время обработки одного товара: 4.7 секунды. Кажется медленнее? Зато мы можем параллелить агентов и обрабатывать сотни товаров одновременно.
Ключевые принципы атомарных промптов
После 10,000 товаров вывел правила, которые теперь применяю ко всем проектам:
- Одна задача = один промпт. Если в промпте есть слово "и" - скорее всего, нужно разбить
- Измеряй точность каждого шага. Нельзя улучшить то, что не измеряешь
- Создай fallback-цепочки. Если агент категорий не уверен (confidence < 80%), отправляй товар на ручную проверку или в более сложный классификатор
- Кэшируй результаты. iPhone 15 встречается 120 раз? Не вычисляй заново, используй кэш
- Логируй все решения. Каждый агент должен оставлять след: что получил на вход, что отдал на выход, какова уверенность
Похожий подход к разбиению задач описан в статье про системного аналитика и ИИ - там тоже рекомендуют дробить сложные процессы.
Техническая реализация
Код выглядит примерно так (упрощенно):
class ProductProcessingPipeline:
def __init__(self):
self.agents = {
'cleaner': CleanAgent(),
'categorizer': CategoryAgent(),
'brand_extractor': BrandAgent(),
# ... остальные 24 агента
}
self.cache = {} # Простой кэш результатов
def process_product(self, raw_name):
# Шаг 1: Очистка
cleaned = self.agents['cleaner'].process(raw_name)
# Шаг 2: Проверка кэша
cache_key = hash(cleaned)
if cache_key in self.cache:
return self.cache[cache_key]
# Шаг 3: Последовательная обработка
result = {}
result['category'] = self.agents['categorizer'].process(cleaned)
# Шаг 4: Ветвление по категориям
if result['category'] == 'Электроника':
result['brand'] = self.agents['tech_brand_extractor'].process(cleaned)
result['specs'] = self.agents['tech_specs_extractor'].process(cleaned)
elif result['category'] == 'Одежда':
result['brand'] = self.agents['fashion_brand_extractor'].process(cleaned)
result['size'] = self.agents['size_extractor'].process(cleaned)
# Шаг 5: Валидация
validation_result = self.agents['validator'].validate(result)
if not validation_result['valid']:
result = self.agents['corrector'].correct(result, validation_result['issues'])
# Шаг 6: Кэширование и возврат
self.cache[cache_key] = result
return resultОшибки, которые стоили нам времени
Не повторяйте эти грабли:
- Слишком умные агенты. Сделали агента "универсальный атрибут-экстрактор". Он пытался извлекать все атрибуты сразу. Точность упала до 71%. Вернулись к специализированным агентам
- Игнорирование confidence score. Первое время брали результат любого агента, даже если он был уверен на 51%. Добавили порог уверенности - качество выросло на 8%
- Нет fallback-механизмов. Агент по определению цвета сломался на товаре "платье цвета морской волны". Весь конвейер встал. Добавили цепочку: основной агент -> резервный агент -> ручная проверка
- Отсутствие A/B тестов. Долго использовали один промпт для извлечения брендов. Потом сделали три варианта, протестировали на 1000 товаров - лучший оказался на 14% точнее
Инструменты для тестирования промптов, подобные тем, что описаны в википедии промптов, могли бы сэкономить нам неделю работы.
Что делать с legacy-промптами?
У вас уже есть монстр-промпт, который кое-как работает? Рефакторинг по шагам:
1Аудит и декомпозиция
Выпишите ВСЕ задачи, которые решает ваш промпт. Каждый глагол - потенциальный отдельный агент.
2Создание прототипов
Для каждой задачи сделайте минимальный промпт. Протестируйте на 50 примерах. Измерьте точность.
3Построение конвейера
Соедините агентов в правильном порядке. Добавьте кэширование и логирование.
4Параллелизация
Найдите независимые задачи - запускайте их одновременно.
Не пытайтесь переписать все за один день. Начните с самого слабого места в вашем промпте. Того, где больше всего ошибок. Разбейте именно эту часть на атомарные шаги - сразу увидите эффект.
Промпт-инжиниринг мертв? Нет, он эволюционировал
Классический промпт-инжиниринг - когда ты часами полируешь одну инструкцию - действительно умер. Но на смену пришло нечто более мощное: инженерия агентов.
Вместо одного сложного промпта вы создаете экосистему простых, специализированных агентов. Каждый решает свою микро-задачу. Вы их комбинируете, тестируете, улучшаете по отдельности.
Это похоже на переход от монолитных приложений к микросервисной архитектуре. Тот же принцип: разделяй и властвуй.
Что в итоге
10,000 товаров обработаны. Точность 94.7%. Система работает автономно, добавляет 500-1000 новых товаров ежедневно. При этом:
- Мы можем улучшать агентов по отдельности. Обновили классификатор цветов - не трогали остальные 26 агентов
- Можем A/B тестировать промпты. Запустили три версии extractor'а брендов, выбрали лучшую
- Понимаем, где система ошибается. Логи показывают: 63% ошибок дает агент определения размеров для обуви. Значит, усилим именно его
- Масштабируемся горизонтально. Больше товаров? Добавляем воркеров, параллелим обработку
Подход с агентами отлично сочетается с идеями из статьи про замену ETL-конвейеров на ИИ-агентов. Та же философия: разбить сложный процесс на простые, надежные шаги.
Следующий шаг - добавить самообучение. Когда агент не уверен в результате, он помечает товар для проверки человеком. Человек исправляет - эта пара "вход-правильный выход" добавляется в few-shot примеры агента. Через месяц система становится на 15-20% точнее без нашего вмешательства.
Промпт-инжиниринг не умер. Он просто вырос из коротких штанишек. Перестаньте писать промпты. Начинайте проектировать агентов.