@stampdwn/llm
v0.1.3
Published
LLM prompt engineering plugin for Stampdown
Downloads
301
Maintainers
Readme
Stampdown Prompt Engineering Plugin
Specialized Stampdown plugin for LLM prompt templating with multi-provider support.
Installation
npm install @stampdwn/llmQuick Start
import { Stampdown } from '@stampdwn/core';
import { llmPlugin } from '@stampdwn/llm';
const stampdown = new Stampdown({
plugins: [llmPlugin]
});
const template = `
{{#withChat raw=chat}}
{{#eachMessage}}
{{#ifUser}}👤 User: {{#firstText this/}}{{/ifUser}}
{{#ifAssistant}}🤖 Assistant: {{#firstText this/}}{{/ifAssistant}}
{{/eachMessage}}
{{/withChat}}
`;
const result = stampdown.render(template, {
chat: {
provider: 'openai',
model: 'gpt-4',
messages: [
{ role: 'user', content: [{ type: 'text', text: 'Hello!' }] },
{ role: 'assistant', content: [{ type: 'text', text: 'Hi there!' }] }
]
}
});Multi-Provider Normalization
The plugin normalizes messages from different LLM providers via @ai-sdk:
- OpenAI (GPT-3.5, GPT-4, etc.)
- Anthropic (Claude)
- Azure OpenAI
- Google Vertex AI
- Custom providers via
@ai-sdk
All providers are normalized to a consistent internal format, so your templates work across any provider.
Helper Reference
Context Normalization
withChat
Normalizes raw chat payload and sets as block context.
{{#withChat raw=chat}}
<!-- chat is now normalized and available as context -->
{{/withChat}}Message Iteration
eachMessage
Iterates over all messages with special variables.
{{#eachMessage}}
**Message** {{@index}}: {{#firstText this/}}
{{/eachMessage}}eachByRole
Iterates over messages filtered by role.
{{#eachByRole role="user"}}
**User** {{@index}}: {{#firstText this/}}
{{/eachByRole}}Role Gates
ifUser, ifAssistant, ifSystem, ifTool
Conditional rendering based on message role.
{{#eachMessage}}
{{#ifUser}}👤 {{#firstText this/}}{{/ifUser}}
{{#ifAssistant}}🤖 {{#firstText this/}}{{/ifAssistant}}
{{/eachMessage}}Content Helpers
eachContent
Iterates over all content items in a message.
{{#eachContent}}
**Type**: {{type}}, **Content**: {{#if type === "text"}}{{text}}{{/if}}
{{/eachContent}}eachText
Iterates over text content only.
{{#eachText}}
{{this}} <!-- text value -->
{{/eachText}}joinText
Joins all text content with separator.
{{#joinText messages sep=" | "/}}firstText, lastText
Gets first or last text content from message.
**First**: {{#firstText message/}}
**Last**: {{#lastText message/}}Windowing & Tokens
window
Selects message range with optional role filter.
{{#window size=5 from="end" role="user"}}
{{#eachMessage}}...{{/eachMessage}}
{{/window}}tokenCount
Counts tokens in text using gpt-tokenizer.
Tokens: {{#tokenCount text/}}truncateTokens
Truncates by token limit with different modes.
<!-- Truncate text -->
{{#truncateTokens text max=100 on="text"/}}
<!-- Truncate message content -->
{{#truncateTokens message max=200 on="message"/}}
<!-- Truncate in block mode -->
{{#truncateTokens max=500 on="block"}}
Long content here...
{{/truncateTokens}}Formatting Helpers
json, yaml, toon
Stringifies value as JSON, YAML or TOON
{{#json chat/}}
{{#yaml config/}}
{{#toon chat/}}renderChat
Converts chat to provider-specific format.
{{#renderChat chat format="json" shape="openai"/}}
{{#renderChat chat format="yaml" shape="anthropic"/}}Custom Tokenizer
Provide your own tokenization logic:
import { llmPlugin, type Tokenizer } from '@stampdwn/llm';
const customTokenizer: Tokenizer = {
count: (text: string) => text.split(/\s+/).length,
truncateByTokens: (text: string, maxTokens: number) => {
const words = text.split(/\s+/);
return words.slice(0, maxTokens).join(' ');
}
};
const stampdown = new Stampdown({
plugins: [
{
...llmPlugin,
options: { tokenizer: customTokenizer }
}
]
});API Docs
Full API reference: packages/llm/docs/index.md
Related Packages
This package is part of the Stampdown ecosystem:
- @stampdwn/core - Core templating engine
- @stampdwn/cli - Command-line interface
- @stampdwn/codemirror - Code mirror language support
- @stampdwn/vscode - VS Code extension
License
MIT
