Перейти к содержимому
13 июн. 2025 г.·6 мин чтения

System prompt для одной модели: почему командам нужны разные правила

Разбираем, почему system prompt для одной модели меняют под словарь команды, правила отказов и нужный формат ответа в рабочих сценариях.

System prompt для одной модели: почему командам нужны разные правила

Где возникает проблема

Проблема начинается в тот момент, когда компания смотрит на модель как на общий инструмент, а на system prompt - как на одну настройку для всех. На коротком демо это почти незаметно. Модель отвечает связно, держит тему и выглядит достаточно умной для любой команды.

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

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

Общий prompt почти всегда дает усредненный результат. Он пытается быть полезным всем сразу и потому становится расплывчатым. В итоге модель пишет вежливо, но не так, как нужно. Она объясняет слишком широко там, где нужен сухой вывод, или отвечает слишком кратко там, где человек ждет контекст.

Самое неприятное в том, что это редко видно на витрине. На 10-20 ручных запросах все может выглядеть нормально. Проблемы всплывают позже, когда запросов становится много, формулировки грязнее, а ответ идет не в чат, а в реальный процесс: в тикет, отчет, внутренний сервис или документ на проверку.

Тогда и начинаются сбои. Один ответ нельзя распарсить. Другой звучит слишком резко для поддержки. Третий выглядит уверенно, хотя данных не хватало и модель должна была остановиться. Если команда работает по формальным правилам, вроде 152-ФЗ или внутреннего аудита, такие промахи уже не выглядят мелочью.

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

Как словарь предметной области меняет смысл

Поведение модели сильнее зависит от словаря команды, чем кажется на старте. Поэтому system prompt редко бывает общим даже для одной и той же модели. Слова в банке, телекоме, ритейле и поддержке значат разное, хотя на вид они знакомые.

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

Сокращения добавляют путаницы. Внутри команды все знают, что такое PII, KYC, SLA или "ручка", но модель не живет в вашем чате и не знает, какое значение принято именно у вас. Она тянется к более частому варианту из обучающих данных. Поэтому "маскирование PII" легко превращается в расплывчатую "защиту личных данных", хотя для юриста, аналитика и разработчика это разные вещи.

Бытовые синонимы тоже часто вредят. Людям они кажутся удобными, а модели дают лишнюю свободу. Если команда пишет то "клиент", то "пользователь", то "абонент", то "контрагент", ответ начинает плавать. Для обычного текста это терпимо. Для маршрутизации тикетов, проверки документов или генерации JSON-полей это уже ошибка.

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

Особенно это видно в командах с регуляторными требованиями. Если одна группа пишет "персональные данные", а модель иногда подставляет "личные данные", текст останется понятным человеку, но станет слабее для внутреннего контроля, поиска по логам и аудита. Там, где важны 152-ФЗ, маскирование PII и стабильные формулировки, такая разница уже влияет на процесс.

Правило простое: если термин влияет на действие, поле в ответе, маршрут запроса или трактовку риска, его нужно явно закрепить в system prompt. Иначе модель заполнит пробелы своим словарем, а не вашим.

Почему правила отказа не бывают общими

Единый system prompt почти всегда ломается на правилах отказа. Одна и та же модель по-разному ошибается в разных командах. Там, где поддержка может продолжить разговор и собрать недостающие данные, риск-команда должна остановить ответ раньше.

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

Возьмем один и тот же вопрос: "Можно провести платеж на нового контрагента?" Для поддержки нормальный ответ - попросить номер договора, сумму и тип операции, а потом направить человека по процессу. Для риск-команды это уже слишком смело. Ей часто нельзя обсуждать допустимость операции, пока не проверены роль пользователя, лимиты, признаки аномалии и внутренние флаги.

Где проходит граница

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

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

Даже сама фраза отказа меняет результат. "Не могу помочь" раздражает и обрывает разговор. "Не могу оценить запрос без номера договора и суммы. Пришлите эти данные" работает мягче и ведет дальше. Но для риск-сценария и такая мягкость иногда вредна: пользователь может принять ее за скрытое разрешение.

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

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

Как формат ответа влияет на интеграцию

Модель может отвечать хорошо для человека и плохо для сервиса. Человек спокойно прочитает абзац с пояснением, а код ждет строгий JSON без лишних слов. Если в начале ответа появится фраза вроде "Готово, вот результат", парсер часто падает сразу.

Из-за этого system prompt нельзя писать только с точки зрения качества текста. Его надо писать под следующий шаг в цепочке. Если после модели ответ забирает CRM, скоринг, роутер или внутренний бот, им нужен предсказуемый формат, а не естественный стиль.

Иногда весь сценарий ломает мелочь. Модель вернула пустую строку перед JSON, добавила комментарий после закрывающей скобки или заменила null на "нет данных". На тестах это выглядит как пустяк. В проде это выливается в лишние ретраи, ручные проверки и странные инциденты.

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

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

Часто нужен не только пользовательский ответ, но и служебная часть. Оператору поддержки хватает поля answer, а риск-команде могут понадобиться еще refusal_reason и confidence, чтобы понять, почему модель отказала и стоит ли отправлять запрос человеку.

{
  "status": "refuse",
  "answer": null,
  "refusal_reason": "not_enough_context",
  "confidence": 0.82
}

Такой контракт звучит скучно, но экономит много времени. Даже если команда подключает RU LLM через OpenAI-совместимый эндпоинт и оставляет привычный SDK, договоренность о формате ответа все равно надо задавать отдельно. Модель может остаться прежней, а интеграция - нет.

Хороший prompt описывает не "красивый ответ", а ответ, который без сюрпризов проходит через код, логику отказов и аудит.

Простой пример с двумя командами

Сравните prompt на моделях
Прогоните один набор кейсов через разные модели и посмотрите, где меньше сбоев.

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

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

Антифроду не нужен разговор. Ему нужен короткий вердикт, который можно сразу передать в правило или интерфейс аналитика: approve, review или decline, плюс код причины вроде card_mismatch или velocity_spike.

Проблема начинается, когда обе команды получают один общий system prompt. Обычно он звучит слишком абстрактно: "будь полезной, точной, безопасной и понятной". Для поддержки этого мало, потому что модель не знает, как объяснять спорные случаи простым языком. Для антифрода этого тоже мало, потому что вместо вердикта она начинает писать рассуждение на несколько строк.

Разница видна сразу. Поддержка ждет ответ вроде: "Возврат уже в обработке. Обычно банк зачисляет деньги в течение 3-5 дней. Если срок пройдет, пришлите номер заказа". Антифрод ждет строку вроде review | reason_code=ip_geo_mismatch | confidence=0.82.

Если оставить один prompt на всех, поддержка получит слишком резкий и машинный стиль. Антифрод, наоборот, получит вежливый текст, который трудно парсить и нельзя стабильно использовать в потоке проверок.

Обычно команды раздражает не сама модель, а смешение ролей. Поддержке нужно, чтобы модель объясняла и успокаивала. Антифроду нужно, чтобы модель не объясняла лишнего и не гадала там, где нужен отказ или ручная проверка.

Как собрать system prompt по шагам

Хороший system prompt редко пишут за один подход. Его лучше собирать как рабочую инструкцию: что делать, где молчать, как отвечать. Если не зафиксировать это в начале, команда потом исправляет ошибки уже после запуска.

  1. Сначала опишите задачу одним предложением. Не "помогай пользователю", а "отвечай как помощник поддержки банка по дебетовым картам и не давай советов по инвестициям". Одно точное предложение убирает половину лишних трактовок.

  2. Затем соберите 20-30 живых запросов. Лучше брать их из чатов, тикетов или внутренних диалогов, а не придумывать вручную. Живые примеры быстро показывают опечатки, жаргон и странные формулировки, на которых модель чаще всего ошибается.

  3. После этого выпишите словарь команды. Сюда входят сокращения, внутренние коды, спорные термины и слова, которые в разных отделах значат разное. Например, слово "лимит" у поддержки карт и у антифрода может вести к разным действиям.

  4. Дальше задайте границы отказа и форму ответа. Модель должна знать, когда можно ответить прямо, когда нужно задать уточняющий вопрос, а когда надо отказать. Здесь же закрепите формат: короткий текст, набор полей, таблица или JSON без пояснений.

  5. Потом прогоните тесты и правьте только спорные места. Обычно быстро всплывают три типа сбоев: модель слишком уверенно выдумывает факт, рано уходит в отказ или ломает формат. Если вы гоняете один и тот же набор кейсов через разные модели, сразу видно, где prompt держится, а где разваливается.

Не пытайтесь поместить в prompt все правила компании сразу. Если правило нельзя проверить на конкретном примере запроса, оно обычно написано слишком общо. Лучше оставить пять ясных ограничений, чем добавлять длинный абзац расплывчатых указаний.

Хороший признак прост: другой человек из команды читает prompt и понимает его без устных пояснений. Еще лучше, если новые запросы не ломают поведение модели, а только уточняют его.

Что команды часто делают не так

Запустите локальные модели
Для низкой задержки и суверенного контура проверьте open-weight модели в российских ЦОДах.

Слабый результат часто связан не с качеством модели, а с тем, как команда пишет инструкции. В system prompt складывают все сразу: тон, правила безопасности, словарь терминов, формат ответа, исключения и внутренние заметки. В итоге модель видит не приоритеты, а шум.

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

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

Плохо работают и запреты без примеров. Фразы вроде "не додумывай", "не давай опасных советов" или "не нарушай политику" звучат строго, но не объясняют, что делать вместо этого. Модели проще следовать правилу, когда рядом есть короткая пара: неверный ответ и допустимый ответ.

Еще один частый сбой возникает, когда в prompt одновременно требуют краткость и полный разбор. Модель не угадает, какое требование важнее в конкретный момент. Если нужен короткий ответ по умолчанию и подробный только в сложных случаях, это надо написать прямо.

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

Быстрая проверка перед запуском

Подключите без миграции
Сохраните свои промпты и код, если нужен единый вход к моделям из РФ.

Перед релизом не смотрите только на качество текста. Проверьте, совпадает ли у команды само понимание правил. Один и тот же system prompt может казаться нормальным до первого спорного запроса, а потом внезапно дать разный ответ у аналитика, юриста и разработчика.

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

Перед запуском стоит проверить пять вещей. Команда должна одинаково толковать спорные термины и сокращения. Модель должна ясно различать, когда надо задать уточняющий вопрос, а когда надо отказать. Ответ должен стабильно проходить по нужной схеме: поля, порядок, типы данных, обязательные блоки. У вас должны быть примеры не только на нормальные, но и на пограничные случаи. И по логам должно быть понятно, почему ответ сломался: из-за prompt, маршрута, схемы или входных данных.

Пограничные случаи полезнее обычных. Дайте модели неполный ввод, конфликтующие инструкции, двусмысленный термин и запрос, который почти нарушает политику отказа. Если она то спрашивает, то отказывает без понятной причины, правило написано слишком расплывчато.

Отдельно проверьте формат. Даже хороший по смыслу ответ не поможет, если интеграция ждет JSON с тремя полями, а модель присылает текст с пояснениями. Один лишний абзац иногда ломает весь пайплайн. Поэтому тестировать надо не только содержание, но и парсинг.

Зрелая настройка prompt обычно узнается по одному признаку: команда может быстро объяснить каждую ошибку. Не "модель странно ответила", а "не хватило определения термина", "правило отказа спорит с форматом" или "в prompt нет указания задавать вопрос при нехватке данных".

Если запросы идут через RU LLM, audit-trails по каждому запросу упрощают такой разбор. Видно, что именно ушло в модель и на каком шаге сломался ответ. Это особенно полезно, когда одна команда винит prompt, а другая - интеграцию.

Что делать дальше

Один общий prompt почти всегда ломается на мелочах. У одной команды свои термины, у другой свои причины для отказа, у третьей строгий JSON без лишнего текста. Поэтому system prompt для одной модели лучше вести как набор отдельных версий, а не как один универсальный текст на всех.

Полезно относиться к prompt как к части продукта. Если команда меняет правило ответа, это изменение должно попадать в версию prompt, в тесты и в примеры. Иначе через месяц никто не вспомнит, почему модель вдруг стала отвечать длиннее, мягче или начала отказывать там, где раньше помогала.

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

Если командам нужен общий вход к моделям, не обязательно строить отдельную интеграцию под каждый сценарий. Ту же развилку по prompt можно держать поверх одного шлюза. Для команд, которым важны локальный биллинг, хранение логов в РФ и OpenAI-совместимый доступ, такой вариант часто проще в эксплуатации.

Имеет смысл сделать одну короткую проверку перед следующим релизом. Возьмите одинаковый набор запросов, прогоните его через текущий prompt и через новую версию, а затем сравните четыре вещи: точность терминов, частоту отказов, стабильность формата и число ручных исправлений после ответа модели. Такой прогон обычно дает больше пользы, чем долгий спор о "лучшем" prompt.

Если после этого различия все еще кажутся мелкими, посмотрите на работу людей вокруг модели. Там быстро видно, где prompt экономит время каждый день, а где добавляет лишнюю проверку к каждому ответу.

Часто задаваемые вопросы

Почему одной модели обычно не хватает одного system prompt на все команды?

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

Один общий prompt почти всегда дает усредненный ответ. На демо это терпимо, а в рабочем потоке начинаются сбои: лишний текст, неверный тон или формат, который не проходит в систему.

Когда общий prompt начинает ломаться в проде?

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

Если после ответа нужен парсинг или аудит, даже одна лишняя строка уже создает проблему.

Что нужно обязательно закрепить в словаре команды?

Сначала зафиксируйте термины, которые меняют действие, маршрут запроса или поле в ответе. Если слово вроде «отказ», «лимит» или «клиент» в отделах значит разное, prompt должен закрепить один нужный смысл для этой роли.

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

Почему поддержке и риск-команде нужны разные правила отказа?

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

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

Как понять, когда модель должна уточнять, а когда сразу отказывать?

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

Такое правило лучше писать на живых примерах, а не общей фразой вроде «не додумывай».

Какой формат ответа лучше задавать для интеграции?

Смотрите не на красоту текста, а на следующий шаг после модели. Если ответ читает код, задавайте строгий JSON без вступлений, пояснений и лишних переносов.

Сразу решите, какие поля обязательны, можно ли ставить null, нужен ли refusal_reason и в каком виде приходит статус. Чем проще контракт, тем меньше сюрпризов в интеграции.

Нужно ли версионировать system prompt отдельно для каждой команды?

Да, иначе никто не поймет, почему поведение модели поменялось через месяц. Для каждой команды держите свой prompt, набор тестовых запросов и ожидаемый формат ответа рядом.

Так проще сравнивать версии и быстро ловить регрессии: лишний текст, неверный термин, слишком ранний отказ или сломанный JSON.

Как быстро проверить prompt перед запуском?

Возьмите короткий набор спорных запросов, а не только удобные примеры. Дайте модели неполный ввод, двусмысленные термины, конфликт инструкций и запросы на грани политики отказа.

Потом проверьте две вещи: смысл ответа и парсинг. Хороший текст не спасает, если система ждет три поля JSON, а модель присылает абзац с пояснением.

Какие ошибки в system prompt команды делают чаще всего?

Часто команды смешивают в одном куске роль, стиль, словарь, запреты и формат. Для человека это еще читаемо, а модель получает шум и начинает выбирать правила наугад.

Еще одна частая ошибка — тестировать prompt только на чистых запросах. Реальные проблемы всплывают на жаргоне, неполных данных и случаях, где роли пересекаются.

Как использовать один шлюз для разных команд и не строить отдельную интеграцию под каждую?

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

Если запросы идут через RU LLM, такой подход не ломает привычный SDK. При этом команде проще разбирать ошибки по логам и audit-trails, когда спор идет между prompt и интеграцией.