Prompt Variables

A prompt template with its slots filled in, beside the exact text the model receives. Variables are parsed out of the template rather than declared separately, so they cannot drift out of sync with it.

src/components/ui/prompt-variables.tsx

About

From the component's own source, where it was written.

A prompt template with its slots filled in, side by side with the result.

Prompt templates fail in one specific way: a variable is renamed in the text and not in the caller, so {{customer}} ships to the model as the literal string {{customer}}. Nothing throws, the model improvises, and the bug is found in an eval three days later.

So the variables are **parsed out of the template** rather than declared separately — they cannot drift, because there is only one list. Anything still unfilled is highlighted in the preview instead of being silently interpolated as an empty string.

The preview is the exact text that will be sent, which is the point. A template view that renders the slots as chips is prettier and answers a different question than "what does the model actually receive".

Install

npx astralyx-ui add prompt-variables

Usage

import { PromptVariables } from '@/components/ui/prompt-variables'

<PromptVariables template={template} values={values} onChange={setValues} />

Composer

Change the props and the source below follows.

Variables

1 unfilled

Drives which refund rules apply.

What the model receives

You are supporting Astralyx.

The customer is Ada Lovelace, on the Team plan.
Their question:

{{question}}

Answer from the retrieved docs. Refunds above £200 go to a human.
Props

No props to configure.

tsx
<PromptVariables
  template={template}
  values={values}
  onChange={setValues}
  multiline={['question']}
/>

Examples

Filling a support prompt

API

Generated from the source, so it cannot fall behind the code. One table per exported component, then hooks, functions and types.

PromptVariables

Extends Omit<ComponentProps<'div'>, 'onChange'>.

PropTypeDefaultDescription
templatestringrequired{{name}} marks a slot. The variable list is derived from this — there is no second list to fall out of step with it.
valuesRecord<string, string>requiredControlled. Unfilled slots are highlighted in the preview instead of being silently interpolated as empty strings.
onChange(next: Record<string, string>) => voidrequiredControlled. Unfilled slots are highlighted in the preview instead of being silently interpolated as empty strings.
multilinestring[][]Which slots get a textarea, and the length past which one is chosen automatically.
hintsRecord<string, ReactNode>—Descriptions per variable, shown under each field.
previewLabelstring'What the model receives'—
variablesLabelstring'Variables'—
missingLabelstring'unfilled'—
multilineAfternumber60Which slots get a textarea, and the length past which one is chosen automatically.

Functions

FunctionSignatureDescription
promptSlots(template: string) => string[]Slot names in the order they first appear. Duplicates collapse.

Behaviour

TopicDetailDescription
previewexact outputThe literal text that will be sent. A view that renders slots as chips is prettier and answers a different question.