Delegation Filter: чек-лист когда НЕ использовать LLM в продакшн-пайплайнах | AiManual
AiManual Logo Ai / Manual.
18 Фев 2026 Гайд

Delegation Filter: когда НЕ использовать LLM в продакшн-пайплайнах (чек-лист от инженера)

Практический чек-лист от инженера: когда НЕ использовать LLM в продакшн-пайплайнах. Delegation Filter для предотвращения дорогих ошибок.

Забыли как писать обычный код?

Помните тот момент, когда впервые запустили GPT-4 и подумали: "Боже, это решает всё"? А потом потратили три недели на отладку RAG-пайплайна, который выдавал случайные факты о динозаврах вместо финансовых отчетов? (Да, это реальная история. Клиент не оценил.)

Мы все прошли через это. LLM-лихорадка. Кажется, что большие языковые модели могут заменить половину кодовой базы. Но на практике получается дорого, медленно и ненадежно.

Вот вам мой личный баг, который стоил компании $15,000 в месяц на лишних API-вызовах:

# Как НЕ надо делать
async def process_document(text: str) -> dict:
    """Извлекаем структурированные данные из документа"""
    prompt = f"""Извлеки из текста:
    - Имя клиента
    - Сумму договора
    - Дату подписания
    
    Текст: {text}
    """
    
    response = await openai.ChatCompletion.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": prompt}]
    )
    
    # Парсим JSON из ответа
    return json.loads(response.choices[0].message.content)

Кажется логичным? А теперь представьте, что этот пайплайн обрабатывает 10,000 документов в день. Каждый вызов к GPT-4o-mini стоит денег. Каждый раз мы парсим JSON, который может сломаться. Каждый раз мы ждем сетевого ответа.

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

Что такое Delegation Filter?

Delegation Filter - это не инструмент и не библиотека. Это ментальная модель. Простой вопрос, который нужно задать перед каждым архитектурным решением:

"Можно ли решить эту задачу детерминированным кодом?"

Если ответ "да" - не используйте LLM. Если ответ "нет" или "можно, но будет сложно" - тогда уже думайте про нейросети.

Звучит очевидно? Посмотрите на свой текущий проект. Сколько там LLM-вызовов, которые можно заменить регулярными выражениями?

Чек-лист: 7 ситуаций, когда НЕ использовать LLM

1 Извлечение структурированных данных из шаблонов

Документы с фиксированной структурой. Договоры, счета, формы. У них есть поля, которые всегда в одном месте.

# Вместо LLM - используйте это
import re
from datetime import datetime

def extract_contract_data(text: str) -> dict:
    """Извлекаем данные из стандартного договора"""
    
    # Ищем паттерны
    client_match = re.search(r"Клиент:\s*(.+)\n", text)
    amount_match = re.search(r"Сумма:\s*(\d+)\s*руб", text)
    date_match = re.search(r"Дата:\s*(\d{2}\.\d{2}\.\d{4})", text)
    
    return {
        "client": client_match.group(1) if client_match else None,
        "amount": int(amount_match.group(1)) if amount_match else None,
        "date": datetime.strptime(date_match.group(1), "%d.%m.%Y").date() 
                if date_match else None
    }

В 100 раз быстрее. В 1000 раз дешевле. На 100% надежнее.

2 Простые классификации

"Это положительный или отрицательный отзыв?" Если у вас есть 1000 размеченных примеров - обучите классификатор. Random Forest, XGBoost, даже логистическая регрессия.

💡
LLM для классификации - это как использовать ракету для поездки в соседний магазин. Да, долетите. Но зачем?

3 Валидация форматов

Проверка email, телефонов, ИНН. Это регулярные выражения. Точка.

Недавно видел в продакшене:

# Реальный код из продакшена (имена изменены)
prompt = "Проверь, что это валидный email: {email}"
response = llm.generate(prompt)
if "да" in response.lower():
    return True

Серьезно? Запускать LLM для проверки email? Это стоит денег. Это создает задержку. И самое главное - это ненадежно.

4 Поиск точных совпадений

Если вам нужно найти в тексте конкретные термины, названия компаний, коды - используйте поиск по подстроке или триграммы. Не семантический поиск.

Семантический поиск отлично работает для похожих смыслов. Но если ищете "ООО 'Рога и копыта'", а LLM находит "компания по производству рогов" - это баг, а не фича.

5 Агрегация числовых данных

Суммирование, средние значения, подсчет. Это математика. Не нужно спрашивать у GPT, сколько будет 2+2.

Хотя... однажды видел, как LLM использовали для подсчета количества строк в CSV. Ответ был: "Примерно 1000 строк, но точное число может отличаться".

6 Роутинг запросов

"Этот запрос про техническую поддержку или про продажи?" Если у вас 5 категорий - сделайте классификатор. Если правила простые - используйте ключевые слова.

LLM для роутинга - это гарантия случайных ошибок. И каждая ошибка означает, что запрос попадет не в тот отдел.

7 Генерация кода по шаблону

CRUD-операции, стандартные API-эндпоинты, миграции баз данных. Используйте шаблонизаторы. Jinja2, Mako, даже f-строки.

LLM будут генерировать разный код каждый раз. Потом этот код нужно тестировать. Потом находить в нем уязвимости.

Когда ИСПОЛЬЗОВАТЬ LLM? Всего 3 случая

Ситуация Почему LLM Пример
Понимание естественного языка Человек пишет свободным текстом "Мне нужна помощь с ошибкой в консоли"
Творческие задачи Нет единственного правильного ответа Генерация маркетингового текста
Работа с неструктурированными данными Документы без четкого формата Анализ переписки в email

Практический пример: фикс RAG-пайплайна

Вернемся к моей истории с динозаврами. Вот как выглядел пайплайн:

# Старый пайплайн (упрощенно)
async def rag_pipeline(query: str, documents: list) -> str:
    # 1. Все документы отправляем в эмбеддинг-модель
    embeddings = await get_embeddings(documents)
    
    # 2. Семантический поиск
    relevant_docs = semantic_search(query, embeddings)
    
    # 3. LLM генерирует ответ
    prompt = f"На основе документов ответь: {query}"
    return await llm.generate(prompt, relevant_docs)

Проблема: 80% запросов были типа "Сколько страниц в документе?" или "Есть ли в документе слово 'договор'?".

Решение - добавить Delegation Filter:

# Новый пайплайн с Delegation Filter
async def smart_rag_pipeline(query: str, documents: list) -> str:
    
    # Delegation Filter: проверяем, можно ли ответить без LLM
    if is_simple_fact_query(query):
        return answer_without_llm(query, documents)
    
    if is_format_validation(query):
        return validate_with_rules(query, documents)
    
    # Только сложные запросы идут в LLM
    embeddings = await get_embeddings(documents)
    relevant_docs = semantic_search(query, embeddings)
    
    prompt = f"На основе документов ответь: {query}"
    return await llm.generate(prompt, relevant_docs)

def is_simple_fact_query(query: str) -> bool:
    """Определяем, можно ли ответить простыми правилами"""
    simple_patterns = [
        r"сколько.*страниц",
        r"есть ли.*слово",
        r"дата.*документа",
        r"автор.*кто",
    ]
    
    for pattern in simple_patterns:
        if re.search(pattern, query.lower()):
            return True
    return False

Результат: стоимость API-вызовов упала на 65%. Задержка уменьшилась в 3 раза. Качество ответов на простые вопросы стало 100%.

Архитектурный паттерн: двухслойная валидация

Лучший способ внедрить Delegation Filter - использовать архитектуру двухслойной валидации. Я подробно писал об этом в статье "Архитектура двухслойной валидации для анализа документов".

Суть проста:

  1. Первый слой: детерминированные правила (регулярки, шаблоны, алгоритмы)
  2. Второй слой: LLM для всего, что не попало в первый слой

Это работает лучше, чем чистая LLM. И дешевле. И надежнее.

Ошибки, которые все совершают

Ошибка 1: Использовать LLM для всего "потому что так проще". Да, написать промпт быстрее, чем алгоритм. Но поддерживать это в продакшене - ад.

Ошибка 2: Не измерять стоимость. Каждый LLM-вызов имеет цену. Умножьте на 1000 запросов в день. Умножьте на 30 дней. Ужаснетесь.

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

Инструменты для внедрения Delegation Filter

Не нужно писать все с нуля. Вот что использую я:

  • Marvin - для построения пайплайнов с условиями "если можно без LLM - не используем LLM"
  • Guardrails - для валидации выходов LLM (да, иногда LLM нужны, но их ответы нужно проверять)
  • Semantic Kernel - для планирования: какие задачи делегировать LLM, какие - обычному коду

Но самый главный инструмент - ваш мозг. И вопрос: "А точно ли здесь нужна нейросеть?"

Что будет дальше?

К 2027 году (да, я заглядываю вперед) мы увидим обратную тенденцию. После хайпа вокруг LLM начнется "возвращение к алгоритмам". Компании поймут, что 80% задач решаются без нейросетей.

Уже сейчас появляются инструменты, которые автоматически определяют, можно ли решить задачу без LLM. Что-то вроде статического анализатора, но для архитектурных решений.

Мой прогноз: через год у каждого уважающего себя инженера будет чек-лист Delegation Filter. Как сейчас у всех есть чек-лист безопасности или code review.

А пока - начните с простого. Возьмите ваш текущий проект. Найдите один LLM-вызов, который можно заменить регулярным выражением. Замените. Посчитайте, сколько сэкономили.

Потом найдите второй. И третий.

Скоро вы заметите, что система стала быстрее, дешевле и надежнее. А главное - вы снова почувствуете себя инженером, а не оператором нейросети.

P.S. Если хотите глубже разобраться в построении пайплайнов, посмотрите мою статью "Как построить семантический пайплайн для LLM". Там есть и про Delegation Filter, и про многое другое.