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

Расширение для внешней генерации блоков (ST 1.14.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

Настройки были перенесены на использование Connection Profiles. Профиль подключения объединяет источник API, модель и прокси в единый профиль. Управлять ими можно в основной панели API Settings.

Расширение предоставляет три настраиваемых API-пресета: Big, Medium и Small. Каждый пресет можно настроить с собственным Connection Profile и параметрами генерации (температура, стриминг и т.д.).

Шаги настройки:

  1. В разделе API Settings на панели ExtBlocks используйте выпадающий список для выбора и настройки каждого пресета (Big, Medium, Small). Для каждого из них выберите Connection Profile и при необходимости измените другие параметры.
  2. В конфигурации каждого блока есть иконка выбора пресета (иконка батареи). Вы можете нажимать на эту иконку, чтобы переключать и назначать один из трех API-пресетов для конкретного блока. Полная батарейка - Big пресет, пустая - Small.

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

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

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

  • Пресеты блоков расположены сверху в 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 - нужно ли вставлять блок в контекст основной генерации
    • Background Generation - должен ли блок генерироваться в фоне
  • Настройки инжекта:
    • 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 - блок будет генерироваться после сообщения чара
    • Generation Pause - приостанавливает генерацию основного ответа при нахождении кейворда. Блоки с этим триггером сгенерируются после остановки, а затем основная генерация продолжится. Поддерживает только кейвордную периодичность.
  • Периодичность - будет ли блок генерироваться с заданным периодом или по определенному кейворду.
  • Период - расстояние между номерами сообщений. Например, если задан триггер 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 - предыдущий блок.
  • Порядок контекста изображен снизу справа, элементы можно передвигать вверх/вниз и удалять. Контекст можно импортировать и экспортировать. Блоки с одинаковым контекстом и триггером будут генерироваться в одной генерации (с учетом периода).

Пример корректной связки имя-шаблон-промпт для генерируемого блока:
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 - имя рерайт блока/блоков, разделенных запятой, обязательный аргумент

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

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

  • Доступ к прошлому блоку можно получить через макрос {{ExtBlocks::имя_блока}}
  • Вызывать генерацию блоков можно через {{ExtBlocks-Call::blocks_names::[additional_prompt]}}. Имена блоков разделены запятой, additional_prompt опционален и имеет тот же смысл, что и в /extblocks-generate.
  • Вызывать рерайт можно через {{ExtBlocks-CallRewrite::blocks_names::[additional_prompt]}}. Аргументы аналогичны.
  • Вызывать скриптовые блоки можно через {{ExtBlocks-CallScript::blocks_names}}. Имена блоков разделены запятой.

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

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

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

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

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

Ссылки:

Edit

Pub: 27 Jul 2024 11:48 UTC

Edit: 19 Dec 2025 04:09 UTC

Views: 5770