Внешние блоки

Расширение для внешней генерации блоков (ST 1.12.0+)

Ссылка - https://gitgud.io/Monblant/extblocks
Установка: Extensions → Install extension (сверху справа) → Вставить ссылку https://gitgud.io/Monblant/extblocks
Обновление: Extensions → Manage extensions (сверху справа) → скролл вниз → кнопка обновить рядом с ExtBlocks


Краткое описание

Обозначения

  • Блок - любая структура, ограниченная XML-тегами <block_name>...</block_name>
  • Основная сетка - API, которая используется для генерации основного ответа
  • Дополнительная сетка - API и конкретная модель, которые используются для генерации блоков

Что делает

  • Автоматически генерирует блоки по триггерам (отправленное сообщение юзера и/или пришедшее сообщение чара), сохраняет блоки в конфиге сообщений
  • Позволяет использовать дополнительную сетку для генерации блоков с отдельными настройками
  • Позволяет редактировать конфиг блоков и создавать пресеты блоков
  • Позволяет встраивать конфиги блоков в карточку персонажа
  • Автоматически создает регексы для блоков, которые скрывают их из основного промпта и из видимости (опционально)
  • Позволяет инжектить блоки на глубину от роли юзера/чара или до/после системпромпта от роли системы

Зачем нужно

  • Собственно генерировать блоки: например, инфоблоки или thinking
  • Не засорять основной промпт инструкциями под блоки
  • Работать в условиях присутствия стопстрингов (например, в случае ноасса)
  • Использовать допсетки (не жечь ключ основной сетки, обходить рейтлимиты, использовать более быстрые и менее заточенные под писательство сетки)
  • Использовать отдельные настройки апи и системпромта/префила для генерации блоков
  • Гарантированная периодичность
  • Отдельный промпт, отдельный контекст - лучшее исполнение инструкций, меньше потерь
  • Раздельность генераций позволяет более эффективно работать с лорбуками

Виды блоков в расширении

  1. Генерируемый блок - блок, который генерируется сеткой
  2. Рерайтовый блок - генерируемый блок, который переписывает основной ответ
  3. Накопительный блок - блок, который обновляется исходя из появления блока-обновителя в основном ответе
  4. Скриптовый блок - блок, который выполняет код на STScript или JS. Если скрипт на JS, лучше почитать, что там написано, прежде чем его запускать.

Настройка

Расширение включается по кнопке Enable ExtBlocks.

API допсетки

Настраивается в API Settings:

  1. Выбирается Chat Completion Source и модель под него:
    • Для OpenAI: модели GPT и совместимые с OpenAI API
    • Для MistralAI: модели Mistral
    • Для Claude: модели Claude
    • Для Gemini: модели Gemini
    • Для OpenRouter: модели Hermes, LLaMa, Phi и LFM
  2. Под выбранную модель выбирается пресет прокси (для OpenRouter можно игнорировать).
  3. Опционально настраивается стриминг, температура, системпромпт и префил

Взаимодействие

Пресеты блоков и встроенные блоки

  • Пресеты блоков расположены сверху в ExtBlocks Preset. Возможные операции с ними: создание нового, импорт из JSON, экспорт в JSON, удаление
  • Ниже в Preset blocks можно добавлять и импортировать из JSON конфиги блоков в пресет
  • Еще ниже в Embedded blocks можно добавлять и импортировать из JSON конфиги блоков в карточку персонажа. Конфиги блоков будут храниться в ней.

Редактирование блоков

Во вкладках Preset blocks и Embedded blocks можно выполнять операции с блоками: включать/выключать, редактировать, экспортировать в JSON, экспортировать промпт в JSON и удалять.

Накопительные блоки

В окне редактирования блоку можно задать:

  • Имя - точное название блока без < и >
  • Имя блока-обновителя - точное название блока без < и > (отличное от вышеупомянутого)
  • Триггеры:
    • User Message - блок будет обновляться исходя из сообщения юзера
    • Char Message - блок будет обновляться исходя из сообщения чара
  • Состояние:
    • Disabled - выключен ли блок (его генерация)
    • Hide From Display - нужно ли прятать блок из видимости для юзера
    • Inject block - нужно ли вставлять блок в контекст основной генерации
  • Настройки инжекта:
    • Injection Role - роль инжекта (система, ассистент или юзер)
    • Injection Position:
      • After Main Prompt и Before Main Prompt - после/до мейнпромпта, корректно работает только с ролью системы. Мейнпромпт должен быть включен в пресете.
      • In Chat - на глубину в чат, корректно работает с ролями юзера и ассистента
    • Injection Depth - глубина инжекта в чат. При отрицательных значениях вставляет блок на глубину с начала чата, при положительных - на глубину с конца.

Пример как должен выглядеть накопительный блок
У строк накопительного блока должна быть постоянная структура Свойство: Значение
Допустимы следующие типы значений: строка (в примере поле Name), число (в примере поле Gold) и массив (в примере поле Inventory).
В массиве строки выглядят как Предмет: Количество предмета (в примере строки Apple и Sword)
Note: Если предмет один, то можно писать просто Предмет без двоеточия и количества (в примере - Map).

1
2
3
4
5
6
7
8
9
<example>
Name: Test
Gold: 100
Inventory: [
  Apple: 4
  Sword: 2
  Map
]
</example>

Пример как должен выглядеть блок-обновитель
В блоке-обновителе поддерживаются несколько операций: присваивание (в примере поле Name), сложение/вычитание для числовых значений (в примере поле Gold), добавление/убирание предмета из массива (в примере поле Inventory).
В сложении/вычитании нет пробела после +, в добавлении/убирании - есть.

1
2
3
4
5
6
<example updater>
Name: User
Gold: +5
Inventory: + Scroll
Inventory: - Apple
</example updater>

Генерируемые блоки

В окне редактирования блоку можно задать:

  • Имя - точное название блока без < и >
  • Тип - инжектовый или рерайт (о нем ниже)
  • Шаблон блока
  • Промпт блока
  • Триггеры:
    • User Message - блок будет генерироваться после сообщения юзера (также после нажатия на свайп, если чат был изменен)
    • Char Message - блок будет генерироваться после сообщения чара
  • Периодичность - будет ли блок генерироваться с заданным периодом или по определенному кейворду.
  • Период - расстояние между номерами сообщений. Например, если задан триггер User message, то чтобы блок генерировался каждое сообщение юзера, нужно задать период 2; каждое второе сообщение - период 4 и т.д. Нечетные периоды имеет смысл задавать только если включены оба триггера.
  • Кейворд - строка, при встрече в сообщении которой будет активироваться генерация блока.
  • Состояние:
    • Disabled - выключен ли блок (его генерация)
    • Hide From Display - нужно ли прятать блок из видимости для юзера
    • Inject block - нужно ли вставлять блок в контекст основной генерации
  • Настройки инжекта:
    • Injection Role - роль инжекта (система, ассистент или юзер)
    • Injection Position:
      • After Main Prompt и Before Main Prompt - после/до мейнпромпта, корректно работает только с ролью системы. Мейнпромпт должен быть включен в пресете.
      • In Chat - на глубину в чат, корректно работает с ролями юзера и ассистента
    • Injection Depth - глубина инжекта в чат. При отрицательных значениях вставляет блок на глубину с начала чата, при положительных - на глубину с конца.
  • Контекст (правая часть редактора) - дополнительная информация для генерации. Доступны несколько видов контекста:
    • Text - свободный текст, работают макросы таверны
    • Last messages - последние сообщения с возможностью прикрепления префиксов/суффиксов. При отрицательном Messages Count выводятся первые сообщения.
    • Last messages by keyword - последние сообщения до встречи определенного кейворда. Полезно для кейворд-триггерных блоков.
    • Previous block - предыдущий блок.
  • Порядок контекста изображен снизу справа, элементы можно передвигать вверх/вниз и удалять. Контекст можно импортировать и экспортировать. Блоки с одинаковым контекстом и триггером будут генерироваться в одной генерации (с учетом периода).

Итоговый промпт генерируемых блока/блоков, который отправляется на допсетку, будет выглядеть так:

  • Склеенный контекст (через \n)
  • \n x 3
  • Склеенные шаблоны блоков (через \n)
  • \n x 2
  • Склеенные промпты блоков (через \n)
  • Отдельно системпромпт и префил (если Claude).

Пример корректной связки имя-шаблон-промпт для генерируемого блока:
Block Name:
current time
Block Template:
<current time>
Time of the day: HH:MM:SS
</current time>
Block prompt:
Write the current time of day in the <current time> block.

Рерайт блоки

Подвид генерируемых блоков, но они никуда не инжектятся - заместо этого они переписывают основной ответ. В редакторе для них есть дополнительный параметр Generation Order - контролирует когда блок будет перезаписывать сообщение, до или после генерации остальных блоков.
В шаблоне рерайт блоки должны содержать блок <rewritten text>, остальное содержание ответа свободное. Имя блока может быть любым, в отличие от обычных генерируемых блоков.

Пример корректной связки имя-шаблон-промпт для рерайт блока:
Block Name:
basic rewrite
Block Template:
<rewritten text>
Rewritten text here
</rewritten text>
Block prompt:
Rewrite the given text.

Скриптовые блоки

В окне редактирования блоку можно задать:

  • Имя - точное название блока без < и >
  • Тип скрипта - STScript или JS
  • Текст скрипта
  • Триггеры, периодичность, состояние - как у генерируемых блоков
  • Порядок выполнения - будет ли скрипт выполняться до или после генерации блоков

API для JS скриптов

Работа с STScript:

(async) executeST(text) - выполняет STScript, подаваемый в функцию в виде строки

Получение блоков:

getAllBlocks() - получает все блоки из текущего пресета и карточки в виде массива
getAllGeneratedBlocks() - получает все генерируемые блоки из текущего пресета и карточки в виде массива
getAllRewriteBlocks() - получает все блоки-переписыватели из текущего пресета и карточки в виде массива
getAllScriptBlocks() - получает все скриптовые блоки из текущего пресета и карточки в виде массива
getAllEnabledBlocks() - получает все включенные блоки из текущего пресета и карточки в виде массива
getPreviousBlockContextUnconditional(block, messageId, may_current, count) - получает предыдущие состояния блока. Аргументы:

  • block - блок, для которого получается состояние
  • messageId - старший номер сообщения, от которого будут искаться состояния блоков
  • may_current - искать ли состояние блока в сообщении с номером messageId. Опциональный аргумент. Допустимые значения: true, false; по умолчанию - false.
  • count - сколько нужно получить предыдущих состояний. Опциональный аргумент, значение по умолчанию - 1.
Работа с блоками:

(async) generateRewrite(rewriteBlock, messageId, allBlocks, additionalMacro) - генерирует блок-переписыватель, возвращая строку. Аргументы:

  • rewriteBlock - сам блок-переписыватель
  • messageId - номер сообщения, для которого генерируется блок
  • allBlocks - массив со блоками, которые релевантны для данного блока-переписывателя (либо просто со всеми блоками)
  • additionalMacro - дополнительные макросы в виде объекта с ключ - строковое значение, например { fruit: 'apple' } позволит воспользоваться в блоке макросом {{fruit}}. Необязательный аргумент.

(async) handleRewriteBlocks(rewriteBlocks, generation_order, messageId, allBlocks, additionalMacro) - генерирует блоки-переписыватели и переписывает заданное сообщение. Аргументы:

  • rewriteBlocks - массив блоков-переписывателей
  • generation_order - фильтрует массив блоков-переписывателей относительно того, генерируются ли они до основных блоков или после. Допустимые значения: 'before', 'after'
  • messageId - номер сообщения, для которого генерируются блоки
  • allBlocks - массив со блоками, которые релевантны для данных блоков-переписывателей (либо просто со всеми блоками)
  • additionalMacro - дополнительные макросы в виде объекта с ключ - строковое значение, например { fruit: 'apple' } позволит воспользоваться в блоке макросом {{fruit}}. Необязательный аргумент.
    (async) handleScriptBlocks(scriptBlocks, execution_order) - выполняет скриптовые блоки. Аргументы:
  • scriptBlocks - массив со скриптовыми блоками
  • execution_order - фильтрует массив скриптовых блоков относительно того, генерируются ли они до основных блоков или после. Допустимые значения: 'before', 'after'

(async) generateBlockContent(blocksInGroup, messageId, allBlocks, additionalMacro) - генерирует блоки, возвращая строку. Аргументы:

  • blocksInGroup - массив генерируемых блоков с одинаковым контекстом (чаще всего массив из одного блока)
  • messageId - номер сообщения, для которого генерируются блоки
  • allBlocks - массив со блоками, которые релевантны для данных генерируемых блоков (либо просто со всеми блоками)
  • additionalMacro - дополнительные макросы в виде объекта с ключ - строковое значение, например { fruit: 'apple' } позволит воспользоваться в блоке макросом {{fruit}}. Необязательный аргумент.

(async) handleGeneration(generatedBlocks, messageId, allBlocks, additionalMacro, is_separate) - генерирует блоки и вставляет их в сообщение. Аргументы:

  • generatedBlocks - массив генерируемых блоков
  • messageId - номер сообщения, для которого генерируются блоки
  • allBlocks - массив со блоками, которые релевантны для данных генерируемых блоков (либо просто со всеми блоками)
  • additionalMacro - дополнительные макросы в виде объекта с ключ - строковое значение, например { fruit: 'apple' } позволит воспользоваться в блоке макросом {{fruit}}. Необязательный аргумент.
  • is_separate - отвечает за то, будут ли блоки вставлены в сообщение с messageId, либо помещены в отдельное новое сообщение от роли системы. Допустимые значения: true, false; по умолчанию - false.

(async) handleBlocksGeneration(messageId, isUser, allBlocks, triggeredBlocks, additionalMacro, is_separate) - отвечает за обработку и генерацию всех блоков для заданного сообщения. Аргументы:

  • messageId - номер сообщения, для которого обрабатываются блоки
  • isUser - идет ли сообщение от роли юзера. Допустимые значения: true, false
  • allBlocks - массив со блоками, которые релевантны для обрабатываемых блоков (либо просто со всеми блоками)
  • triggeredBlocks - массив с блоками, которые будут обрабатываться
  • additionalMacro - дополнительные макросы в виде объекта с ключ - строковое значение, например { fruit: 'apple' } позволит воспользоваться в блоке макросом {{fruit}}. Необязательный аргумент.
  • is_separate - отвечает за то, будут ли генерируемые блоки вставлены в сообщение с messageId, либо помещены в отдельное новое сообщение от роли системы. Допустимые значения: true, false; по умолчанию - false.

injectBlock(block, blockConfig) - вставляет состояние блока в основной контекст. Аргументы:

  • block - состояние блока (строка)
  • blockConfig - конфигурация блока (объект)
Контекст расширения:

extStates - константа-объект, хранящая состояния расширения. Имеет поля:

  • ExtBlocks_settings - настройки расширения
  • current_set - текущий пресет блоков
  • api_preset - текущий API пресет
  • spoilerRegex, self_reload_flag и is_chat_modified - технические значения
Контекст таверны:

context - константа-объект, хранящая функции и состояния таверны. Определена в /public/scripts/st-context.js.

Примеры содержания скриптовых блоков:
  1. Генерация со вставкой блока scene info для последнего сообщения в чате:
    1
    2
    3
    4
    5
    6
    const messageId = context.chat.length - 1;
    const lastMessage = context.chat[messageId];
    const isUser = lastMessage.is_user;
    const allBlocks = getAllBlocks();
    const triggeredBlocks = allBlocks.filter((e) => e.name === 'scene info');
    await handleBlocksGeneration(messageId, isUser, allBlocks, triggeredBlocks);
    
  2. Генерация блока profile в виде строки и ее вывод в консоль браузера:
    1
    2
    3
    4
    5
    const messageId = context.chat.length - 1;
    const allBlocks = getAllBlocks();
    const blocksInGroup =  allBlocks.filter((e) => e.name === 'profile');
    const blockStr = await generateBlockContent(blocksInGroup, messageId, allBlocks);
    console.log(blockStr);
    
  3. Получение четырех предыдущих состояний блока scene info и вывод их в консоль браузера:
    1
    2
    3
    4
    5
    6
    7
    const messageId = context.chat.length - 1;
    const allBlocks = getAllBlocks();
    const blocks = allBlocks.filter((e) => e.name === 'scene info');
    if (blocks.length === 1) {
        const blockStates = getPreviousBlockContextUnconditional(blocks[0], messageId, true, 4);
        console.log(blockStates);
    }
    
  4. Переписывание последнего сообщения с помощью блока basic rewrite, если в сообщении есть выражения-триггеры:
    const messageId = context.chat.length - 1;
    const lastMessageContent = context.chat[messageId].mes;
    const allBlocks = getAllBlocks();
    const rewriteBlocks = allBlocks.filter((e) => e.name === 'basic rewrite');
    const generation_order = 'before';
    
    function containsAnyIgnoreCase(str, substrings) {
        return substrings.some(sub => 
            str.toLowerCase().includes(sub.toLowerCase())
        );
    }
    
    if (containsAnyIgnoreCase(lastMessageContent, ['glint', 'smirk', 'camaraderie'])) {
        await handleRewriteBlocks(rewriteBlocks, generation_order, messageId, allBlocks);
    }
    
  5. Инжект последнего состояния блока scene info:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    const blockName = 'scene info';
    const messageId = context.chat.length - 1;
    const allBlocks = getAllBlocks();
    const blocks = allBlocks.filter((e) => e.name === blockName);
    if (blocks.length === 1) {
        const blockConfig = blocks[0];
        const blockState = getPreviousBlockContextUnconditional(blockConfig, messageId, true);
        injectBlock(blockState, blockConfig);
    }
    

Инициализация блоков

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

Редактирование блоков в сообщении

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

Слэш-команды

  • Генерация блока/блоков - /extblocks-generate. Для команды неважно, включен ли блок. Аргументы:
    • name - имя блока/блоков, разделенных запятой, обязательный аргумент
    • is_separate - при значении true блок создаст новое сообщение от роли системы, необязательный аргумент
    • неименнованный аргумент (ака текст после именованных аргументов) - дополнительный промпт. В промпте, шаблоне и контексте блока доступ к дополнительному промпту осуществляется через локальный макрос {{additionalPrompt}}
Пример команды:
/extblocks-generate name="reflexion, thinking"
  • Перегенерация последних блоков - /extblocks-regenerate
  • Очистка инжектов - /extblocks-flushinjects
  • Добавление блока в хранилище блоков последнего сообщения - /extblocks-storage-append. Аргументы:
    • неименнованный аргумент - строка блока (переносы строк нужно заменить на {{newline}}, а | на \|).
  • Очищение хранилища блоков последнего сообщения - /extblocks-storage-purge.
  • Экспорт всех предыдущих блоков в системное сообщение (полезно при переносе чата) - /extblocks-storage-export
  • Вызов рерайт блоков - /extblocks-rewrite. Для команды неважно, включен ли блок. Аргументы:
    • name - имя рерайт блока/блоков, разделенных запятой, обязательный аргумент
    • неименнованный аргумент (ака текст после именованных аргументов) - дополнительный промпт. В промпте, шаблоне и контексте блока доступ к дополнительному промпту осуществляется через локальный макрос {{additionalPrompt}}
  • Выполнение скриптовых блоков - /extblocks-execute-script. Для команды неважно, включен ли блок. Аргументы:
    • name - имя рерайт блока/блоков, разделенных запятой, обязательный аргумент

Глобальные макросы

Макросы, которые можно применять везде.

  • Доступ к прошлому блоку можно получить через макрос {{extblock:имя_блока}}

Локальные макросы

Макросы, которые можно применять только в промпте, шаблоне и контексте генерируемого блока.

  • Макросы лорбука (только постоянные и те, которые активируются на контекст+шаблон+промпт блока):
    • {{wiBefore}} - записи лорбука с позицией ↑Char
    • {{wiAfter}} - записи лорбука с позицией ↓Char
    • {{wiExamples}} - записи лорбука с позицией ↑EM и ↓EM
    • {{wiDepth}} - записи лорбука с позицией @D
    • {{wiAll}} - все активированные записи лорбука
  • Мейнпромпт текущего пресета - {{mainPrompt}}
  • Дополнительный промпт переданный через слэш-команду - {{additionalPrompt}}

Известные проблемы

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

Ссылки:

Edit

Pub: 27 Jul 2024 11:48 UTC

Edit: 14 Sep 2025 11:33 UTC

Views: 4914