Перейти к содержимому
Docxcelerate

Основы

Статика и динамика

Что разрешается на вашей машине, чему нужен движок и почему граница проходит именно здесь.

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

Вы никогда не объявляете это сами. На каждый вид есть один хелпер, а режим вытекает из переданных ему опций.

Статические узлы

Дайте абзацу render — и его можно построить из ваших данных, а значит, он разрешается локально:

paragraph<OfferData>({
  id: "offer",
  render: (data) =>
    `Your place starts on ${data.startDate}, at ${data.college}.`,
});

Он работает в предпросмотре, в тестах и в сборке — офлайн, мгновенно, бесплатно. Если все узлы документа статические, движок вам вообще не нужен.

Динамические узлы

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

paragraph<OfferData>({
  id: "tutor-note",
  placeholder: (data) => `A note from ${data.interviewer}.`,
  generalPrompt: (data) =>
    `Write two warm sentences about ${data.applicantName}'s interview.`,
});

Тот же хелпер, другие обязательства. image и graph устроены так же — у них роль членов локального разрешения играют src и data.

Почему режим выводится, а не задаётся

Узел с render всегда можно построить локально; узел с одними промптами — никогда. Объявлять режим рядом с этими опциями значило бы завести второй источник истины, способный им противоречить: staticParagraph с generalPrompt или наоборот, плюс какое-то правило приоритета, решающее, кто победит.

Вместо этого истина — сами опции, а mode выводится из них. Указать одновременно render и generalPrompt — это ошибка компиляции, а не подбрасывание монетки во время выполнения.

mode по-прежнему присутствует в собранном DocumentModel и в document.json: движку нужно знать, какие узлы разрешать. Это выход, а не вход.

Доступны четыре слота промптов. Обязателен только generalPrompt:

СлотНазначение
generalPromptЧто узел должен сказать
infoPromptКонтекст, который модель должна знать, но не пересказывать
negativePromptЧего следует избегать
systemPromptУказания о роли и тоне

Что вы видите локально

Сборка для предпросмотра разрешает динамические узлы в их заполнители, а не в сгенерированный текст:

const document = await buildProjectPreviewDocument(project);
// dynamic nodes -> placeholder text

Так задумано. Предпросмотр остаётся детерминированным и бесплатным, так что структуру и оформление можно доводить, не отправляя с машины ни одного запроса. Заполнитель полезен и как дисциплина: если документ с заполнителями невозможно читать, его структура делает слишком мало работы.

Что происходит во время запроса

Артефакт выгрузки сохраняет значения времени запроса в виде токенов вроде {{data.residentName}}, чтобы их можно было разрешить позже. Отправка его движку возвращает готовый документ с заполненными динамическими узлами.

Движок — отдельный бесплатный сервис, который вы размещаете сами. Он намеренно не входит в npm-пакет, так что установка фреймворка никогда не тянет за собой ничего, что требовало бы ключей API или сети. Направьте workspace на свой:

dxcl init my-documents --api-endpoint https://documents.example.com/api/letters
dxcl init my-documents --no-api-endpoint

Значение upload.endpoint в docxcelerate.config.json можно менять в любой момент.

Почему граница проходит здесь

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


Изменить эту страницу на GitHub ↗