Common.AI.Prompts — Универсальный резолвер и сборщик промптов

Автор: Art Yg
Версия: 1.0

Prompts — инфраструктурный helper для унифицированной работы с промптами в сценариях Metabot и внутри других плагинов (например, Common.AI.ImageGen, LLMQuery/LMClient).

Он решает типовую боль: не держать промпты в коде, не копировать одно и то же “склеивание”, и иметь единый механизм:


Зачем он существует

В продуктовых сценариях промпты обычно:

Без Prompts это превращается в дублирование:

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


Основные принципы


Минимальные требования

Для работы в “inline-режиме” достаточно:

  1. lead
  2. вызвать Prompts.buildText(...)

Для работы с табличными ссылками ($... / @...) дополнительно нужно:

  1. наличие table.find в runtime
  2. таблица промптов (promptTable)
  3. агент (agentName) — обязателен только для $name

Что умеет Prompts

1) Ссылки на промпты из таблицы

Поддерживаются два типа ref:

Пример:


2) Макросы (переменные из lead и bot)

Prompts умеет подставлять значения из атрибутов:

Поведение:


3) Нормализация входов и сборка блоков

На вход можно дать:

Дальше Prompts собирает:

И может вернуть:


Конфигурация

Все методы используют общие опции.

DEFAULTS

{
  promptTable: "gpt_prompts",
  agentName: null,   // обязателен для "$name"
  strict: true,      // если промпт не найден → throw
  applyMacros: true
}

Важные правила


API Prompts

Prompts.toArray(value)

Нормализует значение в массив строк.

Используется внутри, но можно использовать и снаружи.


Prompts.resolveOne(ref, opts)

Резолвит одну строку:


Prompts.resolveMany(list, opts)

Резолвит список refs/строк → массив строк.


Prompts.applyMacros(str, lead)

Применяет:


Prompts.buildBlocks(input, opts)

Собирает блоки по секциям:

{
  system: [],
  user: [],
  last: [],
  all: []
}

Prompts.buildText(input, opts)

Собирает итоговый prompt как строку:


Табличный формат промптов

Prompts ожидает, что таблица (promptTable) содержит хотя бы поля:

Запрос выполняется через:

table.find(promptTable, ["prompt"], [
  ["agent_name", agent],
  ["name", name]
]);

Использование

Ниже примеры именно “для статьи”: чтобы читатель увидел, что есть несколько режимов и зачем это.


Примеры

Пример 1 — Inline: без таблиц, без агента

Подходит для простых сценариев и MVP.

const Prompts = require("Common.AI.Prompts");

const prompt = Prompts.buildText(
  {
    system: [
      "You are a strict image generator. Output must be cinematic, realistic, and calm."
    ],
    user: [
      "Create a vertical mythotech Operator icon in Aurum Void aesthetic."
    ]
  },
  { lead } // agentName/promptTable не нужны
);

// prompt — готовая строка, без обращений к таблицам

Пример 2 — Табличный промпт агента: $alias

Если используешь $..., то agentName обязателен, иначе будет throw.

const Prompts = require("Common.AI.Prompts");

const prompt = Prompts.buildText(
  {
    system: [
      "$avatar_brief_generator" // берём из таблицы для агента orion
    ],
    user: [
      "Output should be a codex-grade artifact. No neon. No superhero vibe."
    ]
  },
  {
    lead,
    agentName: "orion",
    promptTable: "gpt_prompts"
  }
);

Пример 3 — Общий промпт: @alias (agentName не нужен)

@name всегда читается из агента <<common>>.

const Prompts = require("Common.AI.Prompts");

const prompt = Prompts.buildText(
  {
    system: [
      "@safety_rules",
      "@style_aurum_void"
    ],
    user: [
      "Create an abstract Operator icon."
    ]
  },
  {
    lead,
    promptTable: "gpt_prompts"
  }
);

Пример 4 — Макросы: подтягиваем контекст из lead и bot

const Prompts = require("Common.AI.Prompts");

// допустим:
// lead.getAttr("actor_stage") = "scaling"
// bot.getAttr("BRAND_TONE") = "discipline, meaning, depth"

const prompt = Prompts.buildText(
  {
    system: [
      "Tone: {{$$BRAND_TONE}}"
    ],
    user: [
      "Stage: {{$actor_stage}}",
      "Create a vertical Operator artifact."
    ]
  },
  {
    lead,
    applyMacros: true
  }
);

Пример 5 — Сборка blocks отдельно (для отладки/логирования)

Иногда полезно видеть, какие блоки получились до склейки.

const Prompts = require("Common.AI.Prompts");

const blocks = Prompts.buildBlocks(
  {
    system: ["@style_aurum_void", "$avatar_brief_generator"],
    user: ["Generate an icon for current stage: {{$actor_stage}}"]
  },
  {
    lead,
    agentName: "orion",
    promptTable: "gpt_prompts"
  }
);

// blocks.system / blocks.user / blocks.all — можно сохранить в lead или tracer

Пример 6 — Мягкий режим (strict=false)

Иногда нужен режим “не падать”, а вернуть сообщение/заглушку.

const Prompts = require("Common.AI.Prompts");

const prompt = Prompts.buildText(
  {
    system: ["$missing_alias"],
    user: ["Create an icon."]
  },
  {
    lead,
    agentName: "orion",
    promptTable: "gpt_prompts",
    strict: false
  }
);

// В strict=false при отсутствии промпта вернётся текст-предупреждение (а не throw)

Использование внутри других плагинов

Common.AI.Prompts специально сделан как “маленький кусок инфраструктуры”, чтобы:

Где он уже естественно применяется


Частые ошибки и как их избежать

1) Использовали $alias, но не указали agentName

Это ошибка по контракту, будет throw:

Решение: передай agentName.


2) Использовали $alias / @alias, но не указали promptTable

Это тоже ошибка:

Решение: передай promptTable (или оставь дефолт "gpt_prompts").


3) Хотели “просто текст”, но случайно начали строку с $

Если текст реально должен начинаться с $, то сейчас это будет воспринято как ref.

Практический паттерн: не начинай “сырой текст” с $/@. Если прям надо — лучше добавить пробел или явную экранировку на уровне твоего контента.


Итог

Common.AI.Prompts — это базовый инфраструктурный helper, который:

Он может использоваться:

Если в твоей архитектуре дальше появятся новые источники промптов (реестр провайдеров, JSON-конфиги, версии промптов, AB-тесты) — вот этот слой и будет правильным местом для расширения. И это как раз тот случай, где можно внезапно сделать себе ловушку, если начать “подмешивать” сюда бизнес-логику — держи его инфраструктурным, иначе потом будет боль.


Версия #2
Artem Garashko создал 1 February 2026 11:39:19
Artem Garashko обновил 1 February 2026 11:49:30