Промпт как микросервис: Разделение сложной задачи на пайплайн

10.06.2026 21:00

Мы все проходили через эту стадию. Вы пишете промпт для обработки пользовательских отзывов. Сначала он выглядит невинно: «Определи тональность текста». Модель справляется отлично. Затем бизнес-заказчик просит добавить извлечение упомянутых брендов. Вы дописываете пару строк. Потом возникает потребность форматировать вывод в строгий JSON. Затем — игнорировать сарказм и классифицировать причину недовольства по справочнику из двадцати пунктов.

Через месяц ваш промпт превращается в хрупкого монстра на 2000 токенов. В нем капсом написано «ОБЯЗАТЕЛЬНО ВЕРНИ JSON, ИНАЧЕ..», а системные инструкции перемешаны с few-shot примерами. Вы тестируете его на новом отзыве, и модель внезапно забывает закрыть скобку в JSON или игнорирует правило про сарказм. Вы добавляете еще один костыль. Цикл повторяется.

Проблема мега-промптов кроется в архитектуре трансформеров. Внимание (attention) рассеивается. Чем больше разнородных инструкций, форматов и ограничений вы загружаете в контекст, тем выше вероятность, что нейросеть проигнорирует часть из них. Эффект «lost in the middle» убивает точность. Попытка решить эту проблему грубой силой — использованием самых тяжелых и дорогих моделей вроде GPT-4o или Claude 3.5 Sonnet для каждой тривиальной задачи — сжигает бюджет проекта и увеличивает время ответа.

Решение лежит в инженерной плоскости. Мы давно перестали писать монолитные функции на тысячи строк в классическом бэкенде. Мы разбиваем логику на микросервисы, каждый из которых делает ровно одну вещь, но делает ее хорошо. Тот же принцип работает с большими языковыми моделями. Пора перестать писать промпты и начать проектировать пайплайны.

Анатомия LLM-пайплайна

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

Рассмотрим классическую задачу: обработка входящего письма от B2B-клиента. Письмо нужно классифицировать, вытащить из него данные договора и сгенерировать черновик ответа.

В микросервисной парадигме этот процесс бьется на три независимых узла:

Узел 1: Классификатор (Router) Задача: определить интент письма (жалоба, запрос документов, техническая проблема). Модель: здесь не нужен выдающийся интеллект. С задачей классификации на 5-10 категорий отлично справляются быстрые и дешевые модели. Через RouterAPI мы можем направить этот запрос в meta-llama/llama-3-8b-instruct. Промпт: строго ограничен списком категорий. Вывод — одно слово.

Узел 2: Экстрактор сущностей (Parser) Задача: найти в тексте номер договора, ИНН компании и сумму претензии, вернув их в JSON. Модель: требуется хорошее понимание контекста и строгое следование формату. Отличный кандидат — google/gemini-1.5-flash. Модель работает быстро и имеет встроенную поддержку JSON-режима. Промпт: схема JSON и текст письма. Никаких инструкций по тональности или стилю.

Узел 3: Генератор ответа (Writer) Задача: написать вежливый ответ, используя данные из предыдущих узлов и базу знаний компании. Модель: здесь важна эмпатия, стиль и естественность языка. Выбираем anthropic/claude-3-haiku или gpt-4o-mini. Промпт: системный промпт с tone of voice компании, интент (из Узла 1) и извлеченные данные (из Узла 2).

Оркестрация через RouterAPI

Реализация такого пайплайна требует гибкого доступа к зоопарку моделей. Привязка к одному провайдеру убивает саму идею оптимизации: у OpenAI нет аналогов сверхдешевой Llama 3 для черновых задач, а у Anthropic нет Gemini Flash с его огромным контекстным окном.

Использование единого шлюза вроде RouterAPI решает проблему инфраструктурного оверхеда. Разработчик использует стандартный клиент OpenAI, меняя только параметр model в зависимости от узла пайплайна.

from openai import OpenAI

client = OpenAI(
 base_url="https://api.routerapi.net/v1",
 api_key="your_token"
)

def process_ticket_pipeline(email_text):
 # Шаг 1: Быстрая классификация (дешево и сердито)
 intent_response = client.chat.completions.create(
 model="meta-llama/llama-3-8b-instruct",
 messages=[
 {"role": "system", "content": "Return ONLY the category: [BILLING, SUPPORT, SALES]."},
 {"role": "user", "content": email_text}
 ],
 temperature=0.1
 )
 intent = intent_response.choices[0].message.content.strip

 # Шаг 2: Извлечение данных (строгий формат)
 entities_response = client.chat.completions.create(
 model="google/gemini-1.5-flash",
 response_format={"type": "json_object"},
 messages=[
 {"role": "system", "content": "Extract order_id and amount as JSON."},
 {"role": "user", "content": email_text}
 ]
 )
 entities = entities_response.choices[0].message.content

 # Шаг 3: Финальная генерация (эмпатия и стиль)
 draft = client.chat.completions.create(
 model="anthropic/claude-3-haiku",
 messages=[
 {"role": "system", "content": "You are a polite B2B manager."},
 {"role": "user", "content": f"Write a reply for {intent}. Data: {entities}. Original: {email_text}"}
 ]
 )
 
 return draft.choices[0].message.content

Экономика и изоляция ошибок

Переход от мега-промпта к пайплайну дает два измеримых преимущества: радикальное снижение затрат и тестируемость.

Когда вы гоняете каждый чих через тяжелую модель, стоимость обработки 10 000 тикетов может достигать сотен долларов. В пайплайне 80% токенов (чтение длинного письма, классификация, парсинг) обрабатываются моделями, которые стоят центы за миллион токенов. Тяжелая артиллерия подключается только на финальном этапе, где требуется качество генерации. Итоговый счет за API падает в 10-15 раз.

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

В пайплайне ошибка локализована. Если система не нашла номер договора, вы тестируете только Узел 2. Вы можете написать классические unit-тесты для каждого вызова LLM. Вы подаете на вход Узла 1 сотню писем и замеряете точность классификации, не тратя время и деньги на генерацию ответов. Промпт-инжиниринг превращается в нормальную программную инженерию.

Скрытые издержки: Latency и State

Архитектура микросервисов всегда несет накладные расходы. В случае с LLM главная проблема — сетевые задержки (latency). Три последовательных вызова API будут работать дольше, чем один большой.

Этот компромисс требует управления. Независимые задачи (например, определение тональности и извлечение ИНН) необходимо запускать параллельно через асинхронные вызовы. Зависимые задачи выстраиваются в цепочку. Если общее время ответа критично (например, в потоковом чат-боте), пайплайн придется оптимизировать, объединяя самые быстрые узлы или используя кэширование семантических ответов.

Вторая сложность — управление состоянием. Данные между вызовами нужно передавать в чистом виде. Если классификатор вместо слова "BILLING" вернет "Я думаю, это категория BILLING", следующий узел сломается. Поэтому жесткий контроль форматов (JSON Schema, регулярные выражения на выходе узлов) становится обязательной частью кода.

Отказ от мега-промптов — это отказ от иллюзии универсального искусственного интеллекта, который "сам во всем разберется". LLM — это не магический оракул, а вычислительный движок с понятными ограничениями. Разделяя сложные задачи на примитивы и оркестрируя их через каталоги вроде RouterAPI, разработчик возвращает себе контроль над системой, делая ее предсказуемой, дешевой и масштабируемой.

Теги

Ещё по теме