Условные промпты ({{#if}})

Блок {{#if}} добавляет часть текста промпта только тогда, когда условие выполняется. Используйте его, чтобы один общий пресет давал разные инструкции разным персонажам, персонам или чатам, или чтобы пропустить пустое поле. Условия – часть системы макросов, поэтому они работают везде, где работают макросы: в карточках персонажей, персонах, записях лорбуков и пресетах.

Marinara проверяет условие при каждой сборке промпта, оставляет подходящий текст, а остальное отбрасывает. Это продвинутая функция, и большинству чатов она не нужна.

Базовый синтаксис

Блок открывается {{#if condition}} и закрывается {{/if}}. Добавьте {{else}} для случая, когда условие не выполняется, и {{else if}}, чтобы выстроить цепочку из нескольких условий. Marinara проверяет ветки сверху вниз и оставляет первую, условие которой выполняется. Если ни одно условие не выполнилось, а ветки {{else}} нет, блок дает пустую строку.

{{#if length == "short"}}
Keep your reply to one or two sentences.
{{else if length == "long"}}
Write a detailed, multi-paragraph reply.
{{else}}
Write a reply of normal length.
{{/if}}

Блок можно записать в одну строку или в несколько, а блоки можно вкладывать друг в друга.

Операторы

Условие обычно состоит из левого значения, оператора и правого значения, например char == "Alice".

ОператорЗначение
==, =, isРавно.
!=, is notНе равно.
>, <, >=, <=Больше, меньше, больше или равно, меньше или равно (только числа).
contains, includesЛевое значение содержит правое как текст.
not contains, not includesЛевое значение не содержит правого.

Правила сравнения:

  1. Для операторов равенства: если обе стороны похожи на числа, Marinara сравнивает их как числа, поэтому 5 равно 5.0. Иначе она сравнивает текст без учета регистра, поэтому Mari равно mari.
  2. Для >, <, >= и <= обе стороны должны быть числами. Иначе условие не выполняется.
  3. contains и includes не учитывают регистр, поэтому contains "dr" находит совпадение в Dr Smith.

Объединение условий

|| означает OR (или), а && – AND (и). && вычисляется раньше ||. Чтобы задать порядок, поставьте скобки.

{{#if character == "Maukie" || character == "Pantalone"}}
Use the shared instructions.
{{/if}}

{{#if (character == "Maukie" || character == "Pantalone") && scenario contains "lake"}}
Use the lakeside instructions for either character.
{{/if}}

Если одно значение сравнивается на равенство с несколькими вариантами, повторяющуюся левую часть можно опустить: character == "Maukie" || "Pantalone". Это работает для ==, = и is. По обе стороны && пишите условия целиком.

Проверка на заполненность

Условие без оператора выполняется, когда в значении есть настоящее содержимое. Оно не выполняется, когда значение пустое или равно одному из слов false, 0, no, off, null или undefined в любом регистре.

{{#if scenario}}
Current scene: {{scenario}}
{{else}}
No specific scene is set.
{{/if}}

Что можно сравнивать

Любой стороной условия может быть:

  1. Ключевое слово поля или личности, например char, user, group, persona, description, personality, scenario, input, model или reasoning. Они берут те же значения, что и одноименные макросы. group перечисляет остальных активных персонажей, кроме того, кто отвечает сейчас.
  2. Литерал в кавычках, например "Alice".
  3. Имя переменной пресета, например length. Смотрите Переменные пресета.
  4. Явное обращение к переменной в виде var:name или var.name.
  5. Другой макрос: сначала раскрывается его значение.
  6. Вопрос вашей модели решений: decision:"..." или decision_choice:"...". Смотрите Вопрос к модели решений.

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

Кавычки

Берите фиксированный текст в простые двойные или одинарные кавычки. Внутри значения в кавычках экранируйте кавычку обратным слешем, а перевод строки записывайте как \n. Литерал с пробелом всегда берите в кавычки, например "Dr Smith". Значение из нескольких слов без кавычек читается как одно имя переменной.

Групповые блоки для нескольких персонажей

В групповом чате с двумя или более персонажами групповой блок повторяет свой текст по одному разу для каждого персонажа. Поставьте одиночную [ на отдельной строке, затем свой текст, затем одиночную ] на отдельной строке. Внутри блока обязателен макрос персонажа, например {{char}} или {{description}}, либо условие по персонажу.

[
{{char}}'s current attitude:
{{#if char == "Alice"}}cheerful and open{{else}}guarded and quiet{{/if}}
]

С Alice и Bob блок сработает дважды, по разу для каждого персонажа. За пределами группового блока макрос персонажа раскрывается только для текущего или основного персонажа. В чате с одним персонажем строки [ и ] остаются обычным текстом.

Примеры

Свой тон для каждого персонажа:

{{#if char == "Dottore"}}
Speak in a cold, clinical tone.
{{else}}
Speak warmly and casually.
{{/if}}

Поле попадает в промпт, только когда оно заполнено. Если поле Backstory (предыстория) пустое, блок дает пустую строку, и пустой заголовок не отправляется.

{{#if backstory}}
Backstory to remember: {{backstory}}
{{/if}}

Инструкции для одного семейства моделей. model – это ID модели, например claude-opus-5-5, поэтому contains подходит ко всем версиям Opus, а == – к одной точной модели.

{{#if model contains "opus"}}
Keep replies under 400 words.
{{/if}}

Инструкции по планированию, которые зависят от рассуждений. Если рассуждения включены на любом уровне, модель получает первую строку. Если они выключены, {{reasoning}} равно off, что читается как ложь. Чтобы сработать на одном уровне, сравните его, как в {{#if reasoning == "max"}}.

{{#if reasoning}}
Plan the reply in your thinking before you write it.
{{else}}
Before replying, write your plan inside <plan></plan> tags.
{{/if}}

Вопрос к модели решений

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

Перед началом: выберите модель в Decision model (модель решений) на панели Connections (подключения). Что это такое и как ее выбрать, объясняет руководство Модели решений. Чтобы решать, активируется ли запись лорбука целиком, используйте вместо этого поле Decision записи.

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

Да или нет: decision:

{{#if decision:"The latest message moves the scene to a new place"}}
Open your reply by describing the new location in one or two sentences.
{{/if}}

Условие выполняется, когда модель решений считает утверждение верным. Оно работает с {{else}}, &&, ||, скобками, вложенностью и групповыми блоками. Макросы в утверждении подставляются заранее, поэтому {{user}} и {{char}} работают. В групповом блоке утверждение с {{char}} запрашивается отдельно для каждого персонажа.

Один из нескольких ответов: decision_choice:

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

{{#if decision_choice:"Kaelen's mood in the latest message" == "angry"}}
Kaelen's lines are short and clipped.
{{else if decision_choice:"Kaelen's mood in the latest message" == "sad"}}
Kaelen speaks quietly and looks away.
{{else}}
Kaelen is his usual self.
{{/if}}

Модель выбирает между "angry", "sad" и "none of these". Пишите утверждение как тему, а варианты – как короткие ответы. Короткая запись == "rain" || "snow" предлагает оба варианта.

Чтобы объяснить, что вариант значит в вашей истории, добавьте после него критерии через двоеточие, взяв обе части в кавычки одного вида: == "angry":"Kaelen raises his voice, makes threats or breaks something". Модель по-прежнему отвечает "angry". Если одному варианту в нескольких местах даны разные критерии, используются первые.

Sticky и cooldown

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

{{#if decision:"The latest message starts a fight" sticky:3 cooldown:5}}
Keep combat pacing rules in effect.
{{/if}}

Для записи лорбука, которая активируется полем Decision (решение), используйте вместо этого собственные Sticky (удержание) и Cooldown (пауза) записи.

Until и while

Чтобы блок оставался включенным, пока что-то длится, добавьте until: или while: со вторым утверждением.

{{#if decision:"A fight starts in the latest message" until:"The fight ends in the latest message"}}
Keep combat pacing rules in effect.
{{/if}}

Если используется sticky, добавьте после второго утверждения :and (или :restrict) либо :or (или :extend), чтобы выбрать, как они сочетаются.

Как записаноПосле да блок остается включенным
until:"..." sticky:5 или until:"...":and sticky:5Не больше 5 следующих сообщений и выключается раньше, если утверждение until окажется истинным.
until:"...":or sticky:5Не меньше 5 следующих сообщений, а затем – пока утверждение until не станет истинным.
while:"..." sticky:5 или while:"...":or sticky:5Не меньше 5 следующих сообщений, а затем – пока утверждение while истинно.
while:"...":and sticky:5Не больше 5 следующих сообщений и выключается раньше, если утверждение while окажется ложным.

Проверка через несколько сообщений

Добавьте every:N, чтобы запрашивать утверждение только раз в N сообщений.

{{#if decision:"The weather changes in the latest message" every:3}}
Describe the new weather in a sentence.
{{/if}}

Приоритет

Если в плане промпта больше утверждений, чем допускает лимит Decision statements per turn, priority:high или priority:low определяет, какие из них спросить. Без приоритета используется средний.

{{#if decision:"In the latest message, a character is badly hurt" priority:high}}...{{/if}}
{{#if decision:"The latest message mentions food" priority:low}}...{{/if}}

Все модификаторы можно сочетать в любом порядке: decision:"..." priority:high sticky:3 cooldown:5 every:2.

Нет ответа означает нет

Условие решения ложно всякий раз, когда ответа нет: модель решений не выбрана, не ответила вовремя или завершилась с ошибкой. Для decision_choice: ложно каждое сравнение. Учитывайте это при написании.

Любая модель может ответить неверно. Пишите для "модели решений", а не для одного конкретного продукта.

Как писать утверждения

Как проверить формулировку:

  1. Выберите модель в Decision model и нажмите Test (проверить). Это проверяет подключение на фиксированном примере. Ваше утверждение при этом не проверяется.
  2. Добавьте утверждение в промпт и отправьте сообщения, на которых оно должно быть истинным, и сообщения, на которых оно должно быть ложным.
  3. Используйте Peek Prompt, чтобы увидеть, какая ветка отправлена. Откройте Decision diagnostics (диагностика решений), затем выберите Test decisions (проверить решения), чтобы заново получить ответы модели решений, не генерируя ответ. Тесты на облачной модели могут стоить денег. Смотрите Проверка условий решений.
  4. Скорректируйте формулировку и проверьте снова. Чтобы видеть ответы во время обычной генерации, включите Debug Mode или отладочное журналирование.

Ограничения и стоимость

Лимит утверждений

Decision statements per turn в Decision model по умолчанию равен 32. Это не единый предел для всех запросов Decision или расходов. Marinara применяет его поэтапно.

  1. Утверждения основного промпта чата планируются в пределах лимита. Решения лорбуков используют то, что осталось.
  2. Агенты, которые работают до ответа или параллельно с ним, получают общий план с основным промптом, и лимит применяется снова. Этот этап не вычитает то, что израсходовал лорбук, поэтому сумма может превысить настройку.
  3. Агенты постобработки получают отдельный лимит после ответа.

Вопросы активации агентов и Smart response order в эту настройку не входят.

В план этапа входят только утверждения, которые он может использовать: включенные секции и группы пресета, выбранные варианты переменных и содержимое активированных записей лорбука. Фиксированное условие может исключить утверждение, например {{#if char == "Dottore" && decision:"..."}}, когда персонаж – Mira. Условие по переменной этого не делает, потому что переменные могут меняться во время сборки промпта. Утверждения, удерживаемые sticky, cooldown или every:, не занимают места. Не вошедшие утверждения означают нет.

Запросы и время

На облачном аккаунте Decision за один ответ может выполняться несколько платных запросов. Утверждения можно группировать, но активация лорбука, содержимое только что активированных записей, рекурсивные совпадения и фазы агентов могут потребовать новых групп. Локальная модель чата добавляет время обработки вместо платы и отвечает на decision_choice: отдельным вопросом да/нет для каждого варианта.

У каждого запроса есть лимит времени: по умолчанию 1,5 секунды для облачного аккаунта Decision или 4 секунды для аккаунта OpenAI-совместимой модели чата или локальной модели. Смотрите Лимиты времени. Локальная рассуждающая модель воздерживается от решений до ответа, если не включить Also gate agents that run before the reply (проверять также агентов до ответа).

Повторное использование ответов

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

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

Кеширование промпта

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

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

На прямом аккаунте Anthropic с включенным Enable prompt caching (включить кеширование промптов) Marinara отмечает конец системного промпта и сообщение чата, отстоящее на Cache depth (глубина кеша) сообщений от последнего (по умолчанию 5). Изменение до истории может сделать недействительными системную границу и последующую историю. Изменение после отмеченной границы истории может сохранить кешированную часть. Минимальная длина кеша зависит от модели. Смотрите актуальное руководство Anthropic по кешированию промптов или руководство OpenAI по кешированию промптов.

Если ветка решения никогда не появляется

Вероятные причины по порядку:

  1. Модель решений не выбрана. Все условия решений ложны. Редактор показывает предупреждение под каждым полем, где они используются.
  2. Модель решений не отвечает: неверный ключ, нет средств или действует ограничение частоты запросов на облачном аккаунте, локальная модель остановлена или слишком медленная, или установленная модель решений не запустилась.
  3. Это рассуждающая модель, которая воздерживается от решений до ответа.
  4. На этапе планирования слишком много утверждений, больше лимита.
  5. Ответ есть, но ниже порога. Обычно дело в формулировке.

Проверьте, что сообщает Test, и откройте Peek Prompt, чтобы увидеть отправленные ветки. Там перечислены утверждения, у которых еще нет ответа: они означают нет. При уровне журнала debug в журнал записываются каждое утверждение, его ответ и то, было ли оно прочитано как да. Смотрите Уровни логирования. Исправлять редко приходится пресет. Обычно дело в формулировке или в ветке, которая несет то, без чего промпт не может обойтись.

Смежные руководства