Table of Contents

Rewrite Text in Different Communication Styles

The same information needs different phrasing for different audiences. A technical explanation for engineers needs to become a concise executive summary. A casual chat response needs to become a professional email. LM-Kit.NET's TextRewriter class transforms text into three communication styles (Concise, Professional, Friendly) while preserving the original meaning. This tutorial builds a text rewriting tool with streaming output and multi-style comparison.


Why Local Text Rewriting Matters

Two enterprise problems that on-device rewriting solves:

  1. Internal communications stay private. Rewriting drafts of sensitive emails, internal memos, and strategy documents means feeding confidential business content into a language model. Local rewriting ensures that content never leaves your infrastructure.
  2. Consistent brand voice at scale. Customer-facing teams write in different styles. A local rewriter standardizes tone across support replies, marketing copy, and documentation without per-request costs.

Prerequisites

Requirement Minimum
.NET SDK 8.0+
VRAM 4+ GB
Disk ~3 GB free for model download

Step 1: Create the Project

dotnet new console -n RewriteQuickstart
cd RewriteQuickstart
dotnet add package LM-Kit.NET

Step 2: Rewrite Text in Three Styles

using System.Text;
using LMKit.Model;
using LMKit.TextEnhancement;

LMKit.Licensing.LicenseManager.SetLicenseKey("");

Console.InputEncoding = Encoding.UTF8;
Console.OutputEncoding = Encoding.UTF8;

// ──────────────────────────────────────
// 1. Load model
// ──────────────────────────────────────
Console.WriteLine("Loading model...");
using LM model = LM.LoadFromModelID("gemma3:4b",
    downloadingProgress: (_, len, read) =>
    {
        if (len.HasValue) Console.Write($"\r  Downloading: {(double)read / len.Value * 100:F1}%   ");
        return true;
    },
    loadingProgress: p => { Console.Write($"\r  Loading: {p * 100:F0}%   "); return true; });
Console.WriteLine("\n");

// ──────────────────────────────────────
// 2. Rewrite in all three styles
// ──────────────────────────────────────
var rewriter = new TextRewriter(model);

string original = """
    Hey team, so basically the server went down last night around 2am because the
    disk was completely full. Nobody noticed until morning when customers started
    complaining. We really need to set up monitoring alerts so this doesn't happen
    again. Also the backup script hasn't been running for like 2 weeks.
    """;

Console.ForegroundColor = ConsoleColor.DarkGray;
Console.WriteLine($"Original:\n  {original.Trim()}\n");
Console.ResetColor();

var styles = new[]
{
    TextRewriter.CommunicationStyle.Concise,
    TextRewriter.CommunicationStyle.Professional,
    TextRewriter.CommunicationStyle.Friendly
};

foreach (var style in styles)
{
    string rewritten = rewriter.Rewrite(original, style);

    Console.ForegroundColor = ConsoleColor.Cyan;
    Console.WriteLine($"{style}:");
    Console.ResetColor();
    Console.WriteLine($"  {rewritten}\n");
}

Step 3: Streaming Output

For longer texts, stream the rewritten output token by token:

using LMKit.TextEnhancement;
using LMKit.TextGeneration;
using LMKit.TextGeneration.Chat;

var rewriter = new TextRewriter(model);

rewriter.AfterTextCompletion += (sender, e) =>
{
    if (e.SegmentType == TextSegmentType.UserVisible)
    {
        Console.Write(e.Text);
    }
};

string input = """
    The deployment process is really messy right now. First you gotta ssh into the
    server, then manually pull the latest code, restart the services one by one, and
    hope nothing breaks. If something goes wrong you have to roll back manually which
    takes forever. We should probably automate this whole thing.
    """;

Console.WriteLine("Professional version:\n");
rewriter.Rewrite(input, TextRewriter.CommunicationStyle.Professional);
Console.WriteLine("\n");

Step 4: Multilingual Rewriting

Rewrite text while targeting a specific output language:

using LMKit.Global;

string englishText = "Our quarterly results exceeded expectations with a 23% increase in revenue.";

// Rewrite in French (Professional)
string french = rewriter.Rewrite(
    englishText,
    TextRewriter.CommunicationStyle.Professional,
    Language.French);
Console.WriteLine($"French (Professional):\n  {french}\n");

// Rewrite in Spanish (Friendly)
string spanish = rewriter.Rewrite(
    englishText,
    TextRewriter.CommunicationStyle.Friendly,
    Language.Spanish);
Console.WriteLine($"Spanish (Friendly):\n  {spanish}\n");

// Rewrite in German (Concise)
string german = rewriter.Rewrite(
    englishText,
    TextRewriter.CommunicationStyle.Concise,
    Language.German);
Console.WriteLine($"German (Concise):\n  {german}\n");

Step 5: Interactive Rewriter

Build an interactive tool that lets users choose the style:

using System.Text;
using LMKit.Model;
using LMKit.TextEnhancement;

LMKit.Licensing.LicenseManager.SetLicenseKey("");

Console.InputEncoding = Encoding.UTF8;
Console.OutputEncoding = Encoding.UTF8;

// ──────────────────────────────────────
// 1. Load model
// ──────────────────────────────────────
Console.WriteLine("Loading model...");
using LM model = LM.LoadFromModelID("gemma3:4b",
    downloadingProgress: (_, len, read) =>
    {
        if (len.HasValue) Console.Write($"\r  Downloading: {(double)read / len.Value * 100:F1}%   ");
        return true;
    },
    loadingProgress: p => { Console.Write($"\r  Loading: {p * 100:F0}%   "); return true; });
Console.WriteLine("\n");

// ──────────────────────────────────────
// 2. Rewrite in all three styles
// ──────────────────────────────────────
var rewriter = new TextRewriter(model);

string original = """
    Hey team, so basically the server went down last night around 2am because the
    disk was completely full. Nobody noticed until morning when customers started
    complaining. We really need to set up monitoring alerts so this doesn't happen
    again. Also the backup script hasn't been running for like 2 weeks.
    """;

Console.ForegroundColor = ConsoleColor.DarkGray;
Console.WriteLine($"Original:\n  {original.Trim()}\n");
Console.ResetColor();

var styles = new[]
{
    TextRewriter.CommunicationStyle.Concise,
    TextRewriter.CommunicationStyle.Professional,
    TextRewriter.CommunicationStyle.Friendly
};

Console.WriteLine("Text Rewriter (enter text, then choose a style)\n");

while (true)
{
    Console.ForegroundColor = ConsoleColor.Green;
    Console.Write("Text: ");
    Console.ResetColor();

    string? input = Console.ReadLine();
    if (string.IsNullOrWhiteSpace(input) || input.Equals("quit", StringComparison.OrdinalIgnoreCase))
        break;

    Console.WriteLine("  [1] Concise  [2] Professional  [3] Friendly  [4] All three");
    Console.Write("  Style: ");
    string? choice = Console.ReadLine();

    if (choice == "4")
    {
        foreach (var style in styles)
        {
            string result = rewriter.Rewrite(input, style);
            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.Write($"  {style,-14}");
            Console.ResetColor();
            Console.WriteLine(result);
        }
    }
    else
    {
        var style = choice switch
        {
            "2" => TextRewriter.CommunicationStyle.Professional,
            "3" => TextRewriter.CommunicationStyle.Friendly,
            _ => TextRewriter.CommunicationStyle.Concise
        };

        string result = rewriter.Rewrite(input, style);
        Console.ForegroundColor = ConsoleColor.Cyan;
        Console.Write($"  {style}: ");
        Console.ResetColor();
        Console.WriteLine(result);
    }

    Console.WriteLine();
}

Step 6: Batch Rewriting

Process a file of messages and export all three style variants:

using System.Text;
using LMKit.Model;
using LMKit.TextEnhancement;

LMKit.Licensing.LicenseManager.SetLicenseKey("");

Console.InputEncoding = Encoding.UTF8;
Console.OutputEncoding = Encoding.UTF8;

// ──────────────────────────────────────
// 1. Load model
// ──────────────────────────────────────
Console.WriteLine("Loading model...");
using LM model = LM.LoadFromModelID("gemma3:4b",
    downloadingProgress: (_, len, read) =>
    {
        if (len.HasValue) Console.Write($"\r  Downloading: {(double)read / len.Value * 100:F1}%   ");
        return true;
    },
    loadingProgress: p => { Console.Write($"\r  Loading: {p * 100:F0}%   "); return true; });
Console.WriteLine("\n");

// ──────────────────────────────────────
// 2. Rewrite in all three styles
// ──────────────────────────────────────
var rewriter = new TextRewriter(model);

string original = """
    Hey team, so basically the server went down last night around 2am because the
    disk was completely full. Nobody noticed until morning when customers started
    complaining. We really need to set up monitoring alerts so this doesn't happen
    again. Also the backup script hasn't been running for like 2 weeks.
    """;

string[] lines = File.ReadAllLines("draft_messages.txt")
    .Where(l => !string.IsNullOrWhiteSpace(l))
    .ToArray();

var output = new List<string>();
output.Add("original,concise,professional,friendly");

Console.WriteLine($"Rewriting {lines.Length} messages...\n");

foreach (string line in lines)
{
    string concise = rewriter.Rewrite(line, TextRewriter.CommunicationStyle.Concise);
    string professional = rewriter.Rewrite(line, TextRewriter.CommunicationStyle.Professional);
    string friendly = rewriter.Rewrite(line, TextRewriter.CommunicationStyle.Friendly);

    output.Add($"\"{Escape(line)}\",\"{Escape(concise)}\",\"{Escape(professional)}\",\"{Escape(friendly)}\"");

    Console.WriteLine($"  Processed: {(line.Length > 50 ? line.Substring(0, 50) + "..." : line)}");
}

File.WriteAllLines("rewritten_messages.csv", output);
Console.WriteLine($"\nExported to rewritten_messages.csv");

static string Escape(string s) => s.Replace("\"", "\"\"");

Common Issues

Problem Cause Fix
Output includes reasoning or preamble Streaming handler not filtering segments Only display TextSegmentType.UserVisible segments
Rewrite changes the meaning Input is ambiguous or too informal Pre-process with TextCorrection to fix grammar first
Output in wrong language Language not specified Pass the target Language parameter explicitly
Slow on long texts Full text processed at once Split into paragraphs; rewrite each separately
Style differences are subtle Small model with limited nuance Use a larger model (gemma3:12b) for more distinct style differences

Next Steps

Share