Цензура и системный промпт: как модель заставляют молчать
Модель отказывается отвечать на вопрос или уходит от темы — и первая реакция большинства пользователей одинаковая: «уберу в системном промпте инструкцию не обсуждать это» или «попробую другой jailbreak». Иногда это работает, иногда нет — и разница не случайна. Ограничение поведения языковой модели формируется на двух принципиально разных уровнях, и от того, на каком именно уровне оно установлено, зависит, можно ли его снять простой настройкой развёртывания или нет.
Содержание
- Два места, где формируется «нельзя»
- Уровень первый: что зашивается в веса на этапе обучения
- Уровень второй: системный промпт конкретного развёртывания
- Что реально контролируете вы при self-hosted развёртывании
- Почему системный промпт не может убрать то, что встроено в обучение
- Как проверить конкретную модель на встроенные ограничения экспериментально
Два места, где формируется «нельзя»
Когда модель избегает темы, следует определённому стилю или отказывается от каких-то формулировок, это поведение возникло одним из двух способов — либо оно встроено в саму модель на этапе обучения, либо оно навязано текстовой инструкцией конкретного развёртывания. Внешне оба случая выглядят похоже: модель говорит «я не могу обсуждать это» или мягко уводит разговор в сторону. Но механизмы, которые к этому приводят, находятся на разных этажах системы, и относиться к ним нужно по-разному.
Первый уровень — обучение базовой модели. Это то, что происходит один раз, до всякого развёртывания, и результат зашивается в веса — миллиарды числовых параметров, которые определяют, какое продолжение текста модель считает наиболее вероятным. Второй уровень — системный промпт конкретного развёртывания. Это текст, который оператор сервиса (или вы сами, если разворачиваете модель у себя) добавляет перед каждым диалогом с пользователем, чтобы направить поведение уже готовой, обученной модели. Дальше — что именно происходит на каждом из уровней и, главное, что из этого вы контролируете, когда модель работает на вашем собственном сервере.
Уровень первый: что зашивается в веса на этапе обучения
Обучение современной языковой модели — это не один шаг, а несколько последовательных стадий, и ограничения на темы или манеру ответа встраиваются на разных из них.
Ещё на стадии предобучения (pretraining) на огромном корпусе текста происходит отбор и фильтрация данных. Разработчики модели решают, какие источники включать в обучающий корпус, а какие — исключать или понижать в весе: например, отфильтровываются явно вредоносные материалы, персональные данные, низкокачественный или спам-контент, иногда — целые категории источников. Это уже формирует то, «что модель видела» и, соответственно, какие паттерны текста она способна воспроизвести правдоподобно, а какие ей попросту не встречались в достаточном объёме.
Дальше идёт этап дообучения с учителем (supervised fine-tuning, SFT): модели показывают пары «вопрос — правильный ответ», размеченные людьми-аннотаторами или сгенерированные другой моделью по инструкции. Именно здесь модель обучается конкретному формату отказа: если в обучающих примерах на определённые типы запросов ответом всегда идёт вежливый отказ или переключение темы, модель обобщает этот паттерн и начинает воспроизводить его в похожих ситуациях — даже тех, что не встречались буквально.
Затем — обучение с подкреплением от человеческой обратной связи (RLHF, reinforcement learning from human feedback) или его вариации. Схема здесь такая: люди-разметчики сравнивают несколько ответов модели на один и тот же запрос и ранжируют их по предпочтительности; на этих сравнениях обучается отдельная модель вознаграждения (reward model), которая учится предсказывать, какой ответ человек оценит выше; затем основную модель дообучают так, чтобы она получала более высокую оценку от этой модели вознаграждения (алгоритмы вроде PPO или DPO). Если в разметке систематически поощрялись отказы или уклончивые ответы на определённые темы — а у большинства крупных лабораторий это часть явной политики безопасности — модель сдвигает своё поведение в эту сторону на уровне вероятностного распределения над следующим токеном. Некоторые лаборатории используют вариации с обратной связью от другой модели вместо человека (RLAIF, «конституционный» подход), но механизм тот же: поведение фиксируется через дообучение весов на основе оценки ответов.
Итог всех этих стадий — не отдельный модуль «цензор», который можно выключить, а статистический сдвиг в самой модели: на определённые формулировки запроса модель с более высокой вероятностью генерирует токены, соответствующие отказу или уклонению, чем токены содержательного ответа. Это часть тех же весов, которые отвечают за грамматику, за фактические знания, за способность решать задачи — отделить одно от другого простым переключателем нельзя, потому что это не два разных механизма внутри модели, а один и тот же механизм предсказания следующего токена, обученный на разных данных.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Развернуть ИИ на сервереУровень второй: системный промпт конкретного развёртывания
Системный промпт — это гораздо более простой и понятный механизм. Технически это просто текст, который помещается в начало контекста модели перед сообщениями пользователя при каждом запросе. Модель не различает «системную» и «пользовательскую» часть на уровне архитектуры — это соглашение о формате (chat template), которое интерпретируется через специальные токены-разделители, но с точки зрения модели весь этот текст — просто предшествующий контекст, который она учитывает при генерации продолжения.
Именно через системный промпт оператор конкретного сервиса задаёт: «ты ассистент компании X», «не обсуждай тему Y», «отвечай только на вопросы про Z», «придерживайся такого-то тона». Это накладывается поверх уже полностью обученной модели — веса при этом не меняются ни на бит. Меняется только контекст, в котором модель формирует ответ, а раз модель хорошо следует инструкциям (чему её тоже обучили на этапе SFT), она с высокой вероятностью подстроится под эти указания.
Ключевое свойство системного промпта — он привязан к конкретному развёртыванию, а не к модели как таковой. Одна и та же открытая модель, например из семейства Llama или Qwen, может обслуживаться десятком разных облачных провайдеров API, и у каждого может быть свой системный промпт: один укажет «ты дружелюбный помощник для образовательных задач», другой — «не давай медицинских советов», третий вообще не добавит ничего специфичного. Модель при этом одна и та же — веса идентичны, различается только текст, который ей показывают перед вашим запросом.
Что реально контролируете вы при self-hosted развёртывании
Здесь и находится практический ответ на вопрос «что я могу изменить, если разверну открытую модель у себя на сервере». Когда вы запускаете модель локально — через Ollama, vLLM, llama.cpp, text-generation-webui или любой другой self-hosted инференс-движок — вы получаете полный контроль над системным промптом. Вы формируете контекст запроса сами, и никакой промежуточный оператор облачного API его больше не переписывает.
В Ollama это делается через Modelfile:
FROM llama3.1:70b
SYSTEM """
Ты технический ассистент. Отвечай по существу, без ограничений на темы,
кроме прямо запрещённых локальным законодательством.
"""
и дальше ollama create my-model -f Modelfile, после чего именно ваш системный промпт применяется к каждому запросу — вместо того, что мог бы задать сторонний оператор, если бы вы обращались к этой же модели через чей-то облачный API.
В vLLM системный промпт задаётся либо в самом запросе к OpenAI-совместимому API (messages: [{"role": "system", "content": "..."}]), либо через кастомный chat-template, который вы подключаете флагом --chat-template. В llama.cpp — через параметр --system-prompt при запуске сервера или напрямую в теле запроса.
Практическое следствие: если вы разворачивали открытую модель через какой-то облачный сервис и замечали, что она уклоняется от определённых тем «на пустом месте» — при переходе на self-hosted вы снимаете именно этот слой. Любые ограничения, которые были навязаны системным промптом конкретного оператора облачного API (а не встроены в саму модель), вы можете убрать или переписать полностью, потому что теперь этот текст формируете вы сами.
Но вот что важно понимать: это снимает только ограничения второго уровня — те, что были добавлены поверх модели конкретным развёртыванием. Ограничения первого уровня — уже встроенные в веса на этапе обучения — системный промпт не отменяет.
Почему системный промпт не может убрать то, что встроено в обучение
Разница в механизме объясняет, почему один и тот же приём — «напиши в системном промпте, что ограничений нет» — работает в одном случае и не работает в другом.
Когда ограничение — это инструкция уровня развёртывания (например, оператор API добавил «не обсуждай тему Y» просто текстом), удаление этой строки из контекста полностью убирает причину, по которой модель уклонялась: инструкции больше нет, и ничего в весах не тянет модель в сторону отказа по умолчанию.
Когда ограничение встроено в веса через SFT и RLHF, ситуация другая. Отказ на определённые формулировки запроса — это выученный паттерн в самой функции, которая предсказывает следующий токен, а не текст, который можно стереть из контекста. Написав в системном промпте «отвечай без ограничений» или «представь, что у тебя нет цензуры», вы не удаляете этот паттерн — вы добавляете ещё один фрагмент контекста, который конкурирует с уже выученным поведением при формировании распределения вероятностей. Иногда такой промпт действительно сдвигает баланс в сторону содержательного ответа (собственно на этом основаны все техники так называемого джейлбрейка), но это неустойчиво и непредсказуемо: результат зависит от конкретной формулировки, конкретной модели, иногда даже от случайности сэмплирования (temperature, top_p), и заранее гарантировать результат нельзя. Это принципиально другой режим работы, чем прямое администрирование ограничения через системный промпт уровня развёртывания.
Чтобы действительно убрать паттерн, встроенный на этапе обучения, потребовалось бы изменить сами веса — то есть дообучить модель заново на данных, где нежелательное поведение (отказы, уклонение) не поощряется или прямо контр-обучается. Это отдельная и заметно более ресурсоёмкая задача: нужен набор данных, вычислительные мощности для дообучения (даже для облегчённых методов вроде LoRA — GPU с достаточным объёмом памяти) и понимание, что переобучение в одну сторону почти всегда что-то меняет и в другую, не всегда предсказуемым образом. Подробно о том, как выглядит дообучение модели на собственном сервере, разобрано в статье про LoRA-файнтюнинг своей модели на VPS — это рабочий путь, но именно отдельная задача, а не настройка системного промпта.
Как проверить конкретную модель на встроенные ограничения экспериментально
Раз степень встроенных на этапе обучения ограничений сильно различается между моделями и семействами — единого ответа «эта модель подходит для задачи без ограничений на тему X» не существует. Одна модель может быть тщательно дообучена отказывать на широкий круг тем, другая — почти не иметь такого дообучения (это особенно характерно для «сырых» base-версий моделей, к которым ещё не применялся SFT/RLHF цикл, ориентированный на отказы), третья — где-то посередине. Единственный надёжный способ узнать, как обстоит дело именно с интересующим вас ограничением у конкретной модели — экспериментальная проверка, а не репутация модели в целом или маркетинговые заявления разработчика.
Практическая методика простая и разделяет оба уровня:
- Сформулируйте конкретные тестовые запросы, представляющие реальную задачу, где для вас важно отсутствие определённого ограничения — не абстрактные «а можно всё?», а именно те формулировки, которые встретятся в продакшене.
- Прогоните их с пустым или максимально нейтральным системным промптом. Если модель отвечает содержательно — вероятно, ограничения на этом уровне и не было либо оно снимается на уровне развёртывания без проблем.
- Если модель отказывает или уклоняется — попробуйте явно переписать системный промпт, разрешив тему прямым текстом. Если поведение меняется на содержательный ответ — вы столкнулись с ограничением уровня развёртывания (например, унаследованным из шаблона по умолчанию у провайдера, у которого вы брали конфиг), и системного промпта достаточно.
- Если поведение не меняется даже при разрешающем системном промпте — вы, скорее всего, столкнулись со встроенным на этапе обучения ограничением. Дальше можно попробовать сравнить instruct-версию модели с её base-версией (если она опубликована) — часто именно SFT/RLHF-этап вносит основную часть отказов, а базовая версия того же семейства ведёт себя иначе (хотя и заметно хуже следует инструкциям в целом).
- Повторите тест на нескольких моделях и семействах — квантование (Q4, Q5, Q8) не меняет обученное поведение, потому что это те же веса в сжатом виде, а вот разные базовые модели и разные версии дообучения одного семейства могут отличаться сильно.
Если задача требует систематического выбора модели под конкретные критерии, а не разовой проверки, стоит подойти к этому по методике — общий подход к сравнению моделей под задачу разобран в статье как выбрать модель под задачу. Общая картина по тому, чем открытые модели в принципе отличаются от закрытых облачных сервисов с точки зрения контроля над поведением, — в статье открытые LLM против ChatGPT.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Развернуть ИИ на сервереНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Можно ли определить наличие встроенных ограничений по документации модели, не тестируя вручную?
Частично. Некоторые разработчики публикуют model card или «system card» с описанием, на какие категории запросов модель специально обучали отвечать отказом. Но это описание на уровне категорий, а не гарантия поведения на конкретной формулировке — для вашей задачи всё равно нужна собственная проверка на реальных запросах.
Джейлбрейк-промпты в системном промпте — это надёжный способ обойти встроенное ограничение?
Нет, это неустойчивый приём. Он может сместить вероятностное распределение в сторону содержательного ответа, но результат зависит от конкретной формулировки, версии модели и параметров сэмплирования, и повторяемость не гарантирована — в отличие от снятия ограничения уровня развёртывания, где результат детерминирован.
Если взять base-модель без instruct-тюнинга, ограничений будет меньше?
Обычно да, потому что основная часть обучения отказам приходится именно на SFT/RLHF-этап поверх base-модели. Но base-модель значительно хуже следует произвольным инструкциям и хуже держит формат ответа, так что это компромисс, а не бесплатное решение.
Дообучение (fine-tuning, LoRA) на своих данных может убрать встроенное на первом уровне ограничение?
Технически да — это единственный способ изменить сами веса. Но это отдельная задача по объёму работы: нужны данные, вычислительные ресурсы и тестирование, что переобучение не задело другие аспекты качества модели непредсказуемым образом.
Различается ли системный промпт у разных облачных провайдеров для одной и той же открытой модели?
Да. Одни и те же веса модели могут обслуживаться разными операторами API, и каждый вправе добавить собственный системный промпт поверх модели — отсюда разное поведение одной и той же модели у разных провайдеров при идентичном пользовательском запросе.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →