Table of Contents

Prompt Templates in LM-Kit.NET: Dynamic Prompt Generation with Logic


TL;DR

Prompt Templates in LM-Kit.NET are compiled template objects that separate prompt structure from runtime data. Using Mustache-style syntax ({{variable}}), they support variable substitution, conditionals (if/else/unless), loops (each), filters (trim, upper, truncate, etc.), scoping (with), inline defaults, and custom helpers. Templates are parsed once via PromptTemplate.Parse() and rendered many times with different PromptTemplateContext instances, making them efficient for high-throughput production systems. They live in the LMKit.TextGeneration.Prompts namespace.


What Are Prompt Templates?

Definition: A Prompt Template is a reusable text structure with placeholders and logic constructs that produces a final prompt string when rendered with runtime data. Unlike simple string interpolation, prompt templates support:

  • Control flow: conditionally include or exclude sections based on variables
  • Iteration: loop over collections to generate lists of tools, constraints, or examples
  • Transformation: apply filters to format values inline (trim whitespace, change case, truncate)
  • Scoping: access nested object properties cleanly
  • Extensibility: register custom helpers and global filters

Why Prompt Templates Matter

+--------------------------------------------------------------------------+
|                  String Concatenation vs. Prompt Templates                |
+--------------------------------------------------------------------------+
|                                                                          |
|  WITHOUT TEMPLATES                 WITH TEMPLATES                        |
|  +---------------------------+    +---------------------------+          |
|  | string prompt =           |    | var t = PromptTemplate    |          |
|  |   "You are " + role +    |    |   .Parse("You are {{role}}|          |
|  |   ". " +                  |    |   .{{#if tools}}Tools:    |          |
|  |   (tools != null          |    |   {{#each tools}}         |          |
|  |     ? "Tools:\n" +        |    |   - {{name}}              |          |
|  |       string.Join(...)    |    |   {{/each}}{{/if}}");     |          |
|  |     : "") +               |    |                           |          |
|  |   "Respond in " + lang;  |    | string p = t.Render(ctx); |          |
|  +---------------------------+    +---------------------------+          |
|  Fragile, untestable,             Clean, testable, versionable           |
|  hard to maintain                  separates structure from data          |
+--------------------------------------------------------------------------+

Key Characteristics

Feature Description
Parse once, render many Template compiles to an AST for fast repeated rendering
Three syntaxes Mustache ({{var}}), Dollar (${var}), Percent (%var%)
Block constructs if/else, unless, each, with (Mustache syntax)
Filter chaining {{name\|trim\|upper\|truncate:20}}
Inline defaults {{language:English}}
Variable introspection template.Variables lists all referenced names
Custom helpers Register functions callable from template expressions
Error reporting PromptTemplateException with line and column info

Prompt Templates in LM-Kit.NET

Core API

using LMKit.TextGeneration.Prompts;

// Parse a template
var template = PromptTemplate.Parse("Hello {{name|capitalize}}!");

// Inspect variables
IReadOnlyList<string> vars = template.Variables; // ["name"]

// Render with context
var context = new PromptTemplateContext { ["name"] = "alice" };
string result = template.Render(context); // "Hello Alice!"

Template Constructs

// Conditionals
var t = PromptTemplate.Parse(@"
{{#if premium}}Detailed answers.{{#else}}Concise answers.{{/if}}
{{#unless banned}}Use examples.{{/unless}}");

// Loops
var t2 = PromptTemplate.Parse(@"Tools:
{{#each tools}}- {{name}}: {{description}}
{{/each}}");

// Scoping
var t3 = PromptTemplate.Parse("{{#with user}}{{Name}} ({{Email}}){{/with}}");

// Custom helpers
var ctx = new PromptTemplateContext();
ctx.RegisterHelper("now", _ => DateTime.UtcNow.ToString("yyyy-MM-dd"));

Prompt Templates vs. String Interpolation

Aspect String Interpolation Prompt Templates
Conditionals Manual if/else in C# {{#if}} in template
Loops Manual string.Join {{#each}} in template
Testability Test entire method Test template + context separately
Version control Embedded in code Store templates as files
Runtime config Requires recompile Swap context at runtime
Error handling Runtime exceptions Parse-time validation

Key Terms

  • Template: A string with placeholders and logic that compiles into a reusable object
  • Context: A PromptTemplateContext holding variable values and helpers
  • Filter: A pipe-separated transformation applied to a variable ({{name|upper}})
  • Helper: A custom function registered on the context and callable from the template
  • AST: The internal compiled representation parsed from the template string
  • Strict mode: Throws PromptTemplateException on missing variables instead of substituting empty strings


  • Prompt Engineering: Core prompting techniques that templates automate
  • AI Agents: Autonomous systems that benefit from dynamic prompt configuration
  • AI Agent Tools: Tool lists that templates can render dynamically
  • Context Windows: Token budgets that template filters (truncate) help manage
  • Chat Completion: The generation process that consumes rendered templates

External Resources


Summary

Prompt Templates in LM-Kit.NET provide a parse-once, render-many template engine for building dynamic prompts. With Mustache-style syntax, they support variables, conditionals, loops, filters, scoping, inline defaults, and custom helpers. Templates separate prompt structure from runtime data, making prompts testable, versionable, and configurable without code changes. They integrate naturally with MultiTurnConversation, AgentBuilder, and all text generation APIs in the SDK.