Zaiets.PromptBuilder 1.0.0

dotnet add package Zaiets.PromptBuilder --version 1.0.0
                    
NuGet\Install-Package Zaiets.PromptBuilder -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Zaiets.PromptBuilder" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Zaiets.PromptBuilder" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Zaiets.PromptBuilder" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Zaiets.PromptBuilder --version 1.0.0
                    
#r "nuget: Zaiets.PromptBuilder, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Zaiets.PromptBuilder@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Zaiets.PromptBuilder&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Zaiets.PromptBuilder&version=1.0.0
                    
Install as a Cake Tool

Zaiets.PromptBuilder

A fluent .NET 8 library for composing prompts to send to LLM APIs. Build system instructions, render templates with named variables, manage conversation history, and check token budgets — all with a clean, chainable API.

Installation

dotnet add package Zaiets.PromptBuilder

Quick Start

using Zaiets.PromptBuilder;

var result = new PromptBuilder()
    .WithSystemPrompt("You are a concise technical writer.")
    .WithTemplate("Explain {{concept}} in one paragraph, targeted at a {{audience}}.")
    .WithVariable("concept", "async/await in C#")
    .WithVariable("audience", "junior developer")
    .Build();

// Send result.Messages to your preferred LLM client
Console.WriteLine(result.FormattedPrompt);
Console.WriteLine($"Estimated tokens: {result.EstimatedTokenCount}");

Features

Feature Description
Fluent API Chainable methods — no boilerplate
Template engine {{variable}} placeholders with strict-mode validation
Chat history Add, trim to token limit, keep last N turns
Token counting cl100k_base-compatible approximation (±10 % for English)
DI support services.AddPromptBuilder() for ASP.NET Core
Immutable messages ChatMessage is a value-like sealed class

API Reference

PromptBuilder

The main entry point. All methods return this for chaining.

var builder = new PromptBuilder();                     // default tokenizer
var builder = new PromptBuilder(myCustomTokenizer);    // custom tokenizer
System prompt
builder.WithSystemPrompt("You are a helpful assistant.");

Replaces any previously set system message.

Templates
builder
    .WithTemplate("Summarise the following in {{language}}: {{text}}")
    .WithVariable("language", "French")
    .WithVariable("text", someArticle)
    .WithStrictTemplates();   // throws TemplateRenderException if a variable is missing
Explicit messages
builder
    .AddUserMessage("What is a monad?")
    .AddAssistantMessage("A monad is a design pattern…")   // few-shot example
    .AddUserMessage("Can you give a C# example?");
Chat history
var history = new ChatHistory()
    .AddSystemMessage("You are a code reviewer.")
    .AddUserMessage("Here is my PR diff: …")
    .AddAssistantMessage("Looks good overall, but consider …")
    .TrimToTokenLimit(3000);

builder.WithChatHistory(history);
Building
PromptResult result = builder.Build();

result.Messages              // IReadOnlyList<ChatMessage> — pass to your LLM client
result.FormattedPrompt       // single string for logging / completion endpoints
result.EstimatedTokenCount   // int — total estimated tokens
result.SystemPrompt          // string? — extracted system message
result.TurnCount             // non-system message count
result.FitsWithin(4096)      // bool
result.TokensRemaining(4096) // int — remaining budget

ChatHistory

var history = new ChatHistory();

history
    .AddSystemMessage("You are helpful.")
    .AddUserMessage("Hello!")
    .AddAssistantMessage("Hi there, how can I help?");

// Trim to a token budget (preserves system messages)
history.TrimToTokenLimit(2048);

// Keep only the last 5 turns
var recent = history.LastNTurns(5);

// Fit into a window without modifying the original
var fitted = history.FitWithin(1500);

// Convenience extension: add a user+assistant pair in one call
history.AddTurn("What is 2 + 2?", "4.");

PromptTemplate

Use standalone when you need template rendering without the full builder.

var tpl = new PromptTemplate("Dear {{name}}, your order {{orderId}} has shipped.");

// Render with a dictionary
string text = tpl.Render(new Dictionary<string, string>
{
    ["name"]    = "Alice",
    ["orderId"] = "ORD-9982"
});

// Check for missing variables before rendering
IReadOnlyList<string> missing = tpl.GetMissingVariables(myVars);

// Inspect declared placeholders
IReadOnlySet<string> declared = tpl.DeclaredVariables;
// → { "name", "orderid" }

ITokenizer / SimpleTokenizer

ITokenizer tokenizer = new SimpleTokenizer();

int tokens = tokenizer.CountTokens("Hello, world!");          // plain string
int tokens = tokenizer.CountTokens(someMessage);              // ChatMessage
int tokens = tokenizer.CountTokens(history.Messages);         // message sequence

Implement ITokenizer to plug in a BPE tokenizer (e.g. Microsoft.ML.Tokenizers).


Dependency Injection (ASP.NET Core)

// Program.cs
builder.Services.AddPromptBuilder();

// Inject PromptBuilder into any service
public class SummaryService(PromptBuilder promptBuilder)
{
    public PromptResult BuildSummaryPrompt(string article) =>
        promptBuilder
            .WithSystemPrompt("You are a summarisation expert.")
            .WithTemplate("Summarise this article in 3 bullet points:\n\n{{article}}")
            .WithVariable("article", article)
            .Build();
}

Custom tokenizer:

builder.Services.AddPromptBuilder<MyBpeTokenizer>();

Conditional sections

builder
    .WithSystemPrompt("You are a code assistant.")
    .When(includeFewShot, b => b
        .AddUserMessage("Reverse a string in C#.")
        .AddAssistantMessage("return new string(input.Reverse().ToArray());"))
    .AddUserMessage(userQuestion)
    .Build();

Token counting accuracy

SimpleTokenizer uses a word-piece length heuristic calibrated against the OpenAI cl100k_base vocabulary:

Text type Typical error
English prose ±5 %
Code (C#, Python, JS) ±10 %
Mixed / non-Latin ±15 %

For production systems that need exact counts, implement ITokenizer using Microsoft.ML.Tokenizers or the tiktoken-dotnet library.


License

MIT © 2025 Vladyslav Zaiets

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 98 5/3/2026

Initial release with fluent prompt building, template rendering, chat history management, and token estimation.