Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → System prompt: инженерия инструкций для LLM

System prompt: как писать инструкции, которые модель соблюдает

Системный промпт: структура, роль и ограничения, формат вывода, примеры, версионирование и тестирование инструкций в LLM-приложениях.

Прямой ответ

System prompt — инструкция, которая задаёт роль модели, границы поведения и формат ответа. Он применяется к каждому запросу и потому определяет поведение сервиса сильнее, чем любой отдельный пользовательский ввод. Практическая цель — получить стабильное поведение, а не «красивый» текст инструкции.

Рабочая структура:

  1. Роль и контекст. Кто модель, для какого продукта работает, на каком языке отвечает.
  2. Задача. Что именно нужно делать, в одном-двух предложениях.
  3. Правила. Ограничения: что запрещено, как отвечать на запросы вне компетенции, как ссылаться на источники.
  4. Формат вывода. Схема JSON, структура ответа, допустимые значения полей.
  5. Примеры. Один-два коротких примера «вход → выход»; для формата они работают лучше длинных объяснений.

Что делает инструкцию соблюдаемой:

  • Короткие утвердительные правила. «Отвечай только на основании предоставленных данных» работает лучше, чем абзац рассуждений о важности точности.
  • Одно правило — одна строка. Списки воспринимаются лучше связного текста.
  • Явное поведение в отказе. Если не указано, что делать при нехватке данных, модель выдумает. Формулировка «Если данных недостаточно, верни not_enough_data» устраняет целый класс галлюцинаций.
  • Формат описан схемой, а не только примером. Примеры дополняют схему, но не заменяют её.

Ограничения, о которых нужно помнить:

  1. System prompt — не защита от инъекций. Пользовательский ввод может содержать инструкции, которые модель попытается выполнить. Меры — в статье про prompt injection.
  2. Длинная инструкция конкурирует за контекст. Каждый запрос несёт её полностью, поэтому раздувание промпта стоит токенов и снижает внимание к остальным данным — см. контекстное окно.
  3. Правила в середине объёмного промпта соблюдаются хуже. Критичные ограничения стоит держать в начале и повторять перед выводом.

Практика: шаблон и организация работы

Пример рабочего системного промпта:

Ты — ассистент классификации обращений поддержки интернет-магазина.

Задача: определить категорию обращения и срочность.

Правила:
- Используй только текст обращения; не додумывай факты.
- Категория — строго из списка: delivery, payment, return, tech, other.
- Срочность — строго из списка: low, normal, high.
- Если данных недостаточно, верни {"error": "not_enough_data"}.
- Не добавляй пояснений вне JSON.

Формат вывода:
{"category": "<значение>", "severity": "<значение>", "reason": "<не более 15 слов>"}

Пример:
Вход: «Заказ не пришёл, деньги списали неделю назад»
Вывод: {"category": "delivery", "severity": "high", "reason": "задержка доставки и списание средств"}

Организация в коде:

  1. Храните промпт как данные, а не как строку в коде. Файл шаблона с версией позволяет менять поведение без правок логики и упрощает ревью.
  2. Версионируйте. Каждая версия промпта — это изменение поведения; привязывайте номер версии к логам запросов, чтобы можно было сопоставить регресс с правкой.
  3. Разделяйте профили. Один промпт на сценарий: классификация, извлечение, свободный ответ. Универсальный промпт «на всё» почти всегда работает хуже.
  4. Тестируйте как код. Набор эталонных входов с ожидаемыми признаками ответа и прогон в CI; методика — в статье про eval для LLM.

Проверка соблюдения формата:

def check_format(answer: str) -> bool:
    import json
    try:
        d = json.loads(answer)
    except json.JSONDecodeError:
        return False
    return (d.get("category") in {"delivery","payment","return","tech","other","error"}
            and d.get("severity") in {"low","normal","high"} or "error" in d)

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

Что не стоит писать в системный промпт. Секреты и токены доступа, внутренние правила авторизации, данные клиентов и длинные справочники. Промпт можно попытаться извлечь, а объёмные данные снижают внимание к правилам; справочную информацию лучше передавать отдельным контекстом с явной разметкой, где заканчивается инструкция и начинаются данные.

Практический сценарий: модель игнорирует запрет на пояснения

Контекст: сервис извлечения данных возвращает JSON с предшествующим текстом «Хорошо, вот результат:», из-за чего парсер падает.

  1. Диагностика. В системном промпте было одно общее предложение про формат и длинный абзац про стиль общения. Запрет на пояснения отсутствовал явно, а единственный пример демонстрировал только JSON.
  2. Изменение. Переписали промпт по структуре: роль — задача — правила списком — схема — пример. Добавили явное правило «Выводи только JSON, без текста до и после».
  3. Проверка параметров. Дополнительно снизили температуру до 0.1 — при 0.7 модель чаще добавляла вводные фразы. Взаимосвязь параметров и формата разобрана в статье про sampling.
  4. Результат. На 300 обращениях доля ответов, начинающихся с {, выросла с 82 % до 100 %; парсер перестал падать.
  5. Профилактика. Промпт вынесен в шаблон с версией, добавлен тест формата в CI и ограничение вывода на стороне движка, где это поддерживается.

Вывод: инструкции соблюдают не «умные», а структурно ясные. Правила списком, явное поведение при отказе и пример формата решают большинство проблем.

FAQ

Насколько длинным должен быть системный промпт? Ориентир — 150–600 токенов для типового сервиса. Если промпт растёт, обычно это признак того, что правила не структурированы или в него перенесли данные, которые должны приходить отдельно.

Помогает ли добавление «ты эксперт мирового уровня»? Как правило, нет: такие формулировки не изменяют поведение измеримо, но расходуют токены. Работают конкретные правила, ограничения и примеры.

Как защищать системный промпт от извлечения пользователем? Полной защиты нет: промпт можно попытаться выпросить или вывести косвенно. Практика: не класть в промпт секреты и внутренние правила доступа, а авторизацию и фильтрацию данных делать вне модели. Подробнее — в статье про prompt injection.

Нужно ли менять системный промпт под разные модели? Да. Модели по-разному реагируют на формулировки и на шаблон чата: то, что стабильно работает на одной, может нарушаться на другой. При смене модели промпт проходит тот же набор тестов, что и при изменении кода.

Источники: Transformers docs (chat templating), OWASP Top 10 for LLM apps, llama.cpp — ссылки в шапке.