Промпты для создания персонажей: двухступенчатая система сохраняет характер после 30+ реплик
Авторы, которые работают с ИИ-персонажами в ролевых проектах или чат-ботах, знают главную боль: через двадцать-тридцать реплик характер «плывёт», и модель забывает, кем должна быть.

Проблема не в слабой модели, а в архитектуре промпта: один длинный системный промпт деградирует по мере роста контекстного окна (область памяти, которую модель видит за один ход). Двухступенчатая система с тегами реакций решает это на уровне логики, а не надежды.
Автор открытого проекта по созданию ИИ-персонажей больше полугода тестировал способы удержать консистентность характера в длинных диалогах. Итог: вместо одного раздутого промпта он разбил каждый ход на два вызова модели и ввёл жёсткий набор допустимых реакций, «тегов», которые движок выбирает детерминированно, а модель лишь отыгрывает. Ниже разбираем метод пошагово, с кодом и конкретным примером.
Что понадобится
- Доступ к языковой модели с поддержкой структурированного вывода (JSON-формат ответа): подойдут API OpenAI, локальные модели через Ollama или LM Studio
- Python 3.10+ и базовое умение запускать скрипты
- Подготовленный «пак» персонажа: описание личности, список тегов реакций с дельтами (что это, объясню ниже)
- Примерно 2 часа на первую настройку, потом каждый новый персонаж занимает 20 минут
Пошаговая инструкция: семь шагов к устойчивому характеру
1. Составьте список допустимых реакций (тегов)
Определите набор эмоциональных реакций, которые персонаж может проявить. Это не свободный текст, а закрытый перечень. Для юной архимаг Мегумин из «Konosuba» автор проекта использует теги вроде «взрыв энтузиазма», «показная холодность», «смущение» и другие, характерные именно для неё.
Каждый тег привязан к конкретному набору текстовых инструкций, которые модель получит на втором шаге.
2. Настройте классификатор момента (первый вызов модели)
Классификатор получает только последние 6 реплик диалога и список ваших тегов. Его задача: выбрать один тег, подходящий к текущему моменту. Температура (параметр случайности) здесь строго нулевая, модель не импровизирует, а выбирает из закрытого перечня.
schema = {
"type": "object",
"properties": {
"tag": {
"type": "string",
"enum": [t.id for t in pack.tags]
}
},
"required": ["tag"]
}
raw = self._llm.chat(messages, fmt=schema, options={"temperature": 0.0})
Бэкенд физически не может вернуть тег, которого нет в списке. Если ответ не парсится, система делает одну повторную попытку и откатывается на тег по умолчанию. Ход не падает никогда.
3. Разверните тег в текстовые инструкции
Выбранный «сухой» тег (например, explosion_enthusiasm) разворачивается в понятный модели блок текста: «Персонаж сейчас в состоянии восторга, говорит быстро, упоминает взрывную магию, перебивает собеседника».
4. Соберите двухсегментный промпт для генерации (второй вызов модели)
Второй вызов собирает полный контекст:
- Стабильный префикс: описание личности и неизменные черты персонажа. Этот блок вшивается один раз, а его KV-кэш (внутреннее представление уже обработанных токенов) переиспользуется между ходами
- Динамический хвост: текущая стадия отношений, развёрнутый блок тега, релевантные воспоминания из векторной памяти и последнее сообщение пользователя
Температура здесь выше: модель импровизирует, но строго в границах полученного тега.
5. Добавьте числовые оси состояния
Тег это «погода» одного хода. Чтобы из отдельных реакций рос характер отношений, автор проекта ввёл три числовые оси:
affection(симпатия)trust(доверие)bond(привязанность)
Каждому тегу в паке персонажа сопоставлен вектор дельт: насколько он сдвигает каждую ось. Модель эти числа не видит и не влияет на них. Двигает оси только движок по фиксированной таблице.
def apply(self, delta):
for name in ("affection", "trust", "bond"):
self._values[name] = clamp(
self._values[name] + getattr(delta, name),
0.0, self._max
)
return self.axes
Между ходами работает механизм затухания (decay): на паузах оси тянутся обратно к базовой линии, чтобы диалог не «залипал» на эмоциональном пике.
6. Настройте стадии отношений
Стадия это «климат», а не «погода». Текущая стадия вычисляется как процент от максимума осей. Параметр axis_max позволяет управлять скоростью: поставьте 1000 вместо 100, и те же дельты станут меньшей долей от целого. Персонаж будет теплеть медленнее (slow-burn), а сам пак менять не нужно.
Ось bond намеренно сделана медленной: её дельта по правилу движка никогда не превышает дельты симпатии и доверия.
7. Проверьте полный цикл хода
Вот как выглядит один ход целиком:
- Сообщение пользователя поступает в классификатор
- Классификатор выбирает тег из закрытого перечня
- Движок сдвигает числовые оси по таблице дельт и пересчитывает стадию
- Генератор получает стабильный префикс, диалоговое окно и динамический хвост с тегом, стадией и памятью
- Модель озвучивает ответ персонажа
- Реплика сохраняется в память
Допустим, вы создаёте персонажа для RP-бота в Telegram. Персонаж: Мегумин, юная архимаг, помешанная на взрывах. Пользователь пишет: «Давай сходим в таверну». Классификатор получает последние 6 реплик, видит мирный контекст и выбирает тег, допустим, «скучающее согласие». Движок чуть сдвигает ось симпатии вверх. Генератор получает: личность Мегумин плюс инструкцию «персонаж соглашается нехотя, может вставить реплику о том, что в таверне нет достойных целей для взрывной магии». Результат: ответ остаётся в характере, даже если предыдущие 30 реплик были совершенно другими по настроению. Модель не «забывает» персонажа, потому что тег принудительно задаёт вектор каждого хода.
Один гигантский системный промпт. Новички пишут промпты для создания персонажей в виде монолита на 2000 слов и надеются, что модель всё удержит. Контекстное окно работает иначе: чем длиннее текст, тем выше шанс, что часть инструкций будет проигнорирована. Разделяйте стабильное (личность) и динамическое (тег хода).
Температура не ноль на классификаторе. Если дать модели свободу на этапе выбора тега, она начнёт «фантазировать» реакции и выходить за рамки персонажа. Нулевая температура для классификатора, это не ограничение, а предохранитель.
Нет fallback-тега. Если ответ классификатора не парсится и отката нет, ход ломается. Всегда объявляйте тег по умолчанию в паке персонажа.
Модель видит числа осей. Передавать в промпт сырые значения affection=73.5 бессмысленно и вредно: модель не понимает, что с ними делать. Числа обрабатывает движок, модель получает только текстовый результат: стадию и развёрнутый тег.
Нет decay между ходами. Без затухания оси быстро упираются в потолок, и персонаж «залипает» в состоянии максимальной привязанности после десятка тёплых реплик.
Что делать с этим прямо сейчас?
Авторам Дзена и копирайтерам. Промпты для создания персонажей по этой схеме работают не только в RP. Если вы ведёте канал от лица персонажа-эксперта или маскота бренда, двухступенчатая логика (классификатор плюс генератор) поможет сохранить единый голос в серии постов. Не обязательно писать код: достаточно вручную выбирать тег настроения перед каждым промптом и вставлять его отдельной строкой в системный промпт (системный промпт, это постоянная инструкция, которую модель получает до вашего сообщения).
Разработчикам ботов и RP-проектов. Код из статьи открыт и работает с любой моделью, поддерживающей JSON-формат ответа. Из доступных в РФ инструментов: Ollama с локальными открытыми моделями, LM Studio, а для облачных задач GigaChat API от Сбера поддерживает структурированный вывод.
Предпринимателям в РФ и СНГ. Если вы строите продукт с ИИ-ассистентом (поддержка клиентов, обучающий бот, игровой компаньон), эта архитектура решает конкретную бизнес-задачу: пользователь не сталкивается с «расщеплением личности» бота на двадцатой реплике.
По моему опыту, главная проблема длинных диалогов с ИИ-персонажами действительно не в модели, а в том, как мы подаём ей контекст. Я проверял: один и тот же персонаж на одной и той же модели «плывёт» через 15 ходов с монолитным промптом и держится стабильно с разделением на классификатор и генератор. Метод из статьи требует минимального умения работать с Python, но идею, фиксированный набор реакций плюс принудительный выбор перед генерацией, можно адаптировать даже в ручном режиме через ChatGPT или Claude. Честная оговорка: автор тестировал метод на своём проекте, массовых бенчмарков нет, и результат зависит от конкретной модели и длины пака.
Разделение «погоды» (тег) и «климата» (стадия) даёт персонажу то, чего не может дать даже идеальный промпт: возможность быть непредсказуемым в моменте и последовательным в развитии. Попробуйте начать с пяти тегов и трёх осей для одного персонажа, этого хватит, чтобы увидеть разницу уже на первом длинном диалоге.
Генератор промптов dzen.guru
Соберите системный промпт для вашего ИИ-персонажа за пять минут, с разделением на стабильный блок и динамические теги
Попробовать генератор
Основатель dzen.guru. Эксперт по монетизации и продвижению на Дзен. Автор курса «Старт на Дзен 2026».
Читайте также
Meta превращает ИИ-ассистент в рабочий инструмент: календарь, отчёты и поиск товаров
Meta второго июня начала превращать свой ИИ ассистент Meta AI из развлекательного чат-бота в рабочий инструмент, который сам читает календарь, ищет товары и…

Машинное обучение (machine learning) это магистратура за год: МАИ сжал программу вдвое
Машинное обучение (machine learning) это область, где технологии устаревают быстрее, чем университеты успевают обновить программу, и МАИ попробовал решить эту…

Искусственный интеллект и светофоры: почему выбор целевой функции важнее алгоритма
Стоп. Заданный H1 и архетип (how-to с пошаговой инструкцией) не совпадают с содержанием оригинала. Оригинал — это аналитическая статья о том, почему…
Комментарии