Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 15

Mastering Brand Voice with LLMs

Recommended resources

Hello! Welcome back.

In our last lesson, we built the strategic backbone of our content system by generating structured outlines from our trend analysis. We now have a clear, machine-readable blueprint for what we want to say. The next challenge is how we say it.

Today's lesson addresses the learning outcome: Apply brand voice constraints and few-shot examples to control LLM-generated content style. This is where we move from a generic "AI voice" to a distinctive, consistent style that reflects your personal brand. For your goal of creating engaging content, this step is critical. A strong voice is what transforms dry technical information into compelling thought leadership.

We will explore two powerful techniques:

  1. Brand Voice Constraints: Systematically telling the LLM who to be and what rules to follow.
  2. Few-Shot Prompting: Showing the LLM what you want through concrete examples.

By the end of this lesson, you will have implemented a "Writer Agent" in TypeScript that takes a content outline and generates text that adheres to a predefined style.

The Problem: Generic, Inconsistent AI Output

If you simply give an LLM an outline and ask it to write, you'll get unpredictable results. The tone might shift from one generation to the next, and the style will likely be bland and corporate. This is a "zero-shot" approach—asking the model to perform a task with zero examples.

To understand the limitations of zero-shot prompting and the power of providing examples, it's helpful to see it in action.

Zero, One, and Few Shot Prompting with Langchain and OpenAI LLMs

The video 'Zero, One, and Few Shot Prompting' provides an excellent demonstration of why providing examples is so crucial for getting consistent and well-formatted LLM outputs.

Watch the following segments to see the progression: Zero-Shot (03:27 - 05:58): Notice how running the same simple prompt yields different, unstructured results each time. One-Shot (05:58 - 13:03): See how just one example starts to provide structure, but can still be limited. Few-Shot (13:03 - 18:58): Observe how multiple, diverse examples give the model a much clearer understanding of the desired output format, even with more complex requirements. While the code is in Python, the core principles of structuring prompts with examples are universal and directly apply to our TypeScript project.

As the video shows, providing examples—few-shot prompting—is a powerful way to guide the model. But before we provide examples of our style, we need to define it.


Defining Your Style: Brand Voice Constraints

Instead of a single-line instruction like "write in a professional tone," we will use a more robust, layered approach to define your brand voice. This turns a vague "vibe" into a set of concrete, machine-readable instructions.

Prompt Engineering for Brand Voice: Advanced Techniques | Atom Writer Blog

The article 'Prompt Engineering for Brand Voice: Advanced Techniques' offers a superb framework called the 'Layered Prompt Architecture.' We will adopt this structure for our project.

Read the sections on 'The Layered Prompt Architecture,' focusing on: Layer 1: System Role Assignment: How to give the AI a specific persona. Layer 2: Voice Rules With Measurable Criteria: The importance of concrete rules (e.g., sentence length) over vague adjectives. Layer 3: Few-Shot Voice Examples: How examples complement rules. Pay special attention to the concept of contrastive few-shot prompting (showing a 'generic' vs. 'on-brand' example).

This layered architecture provides a robust template for our system prompt. By defining a role, setting measurable rules, and providing examples, we constrain the LLM's output space, forcing it to generate content that aligns with our desired style.


Guiding with Examples: The Power of Few-Shot Prompting

Rules tell the AI what to do, but examples show it what the result looks like. This is the essence of few-shot prompting.

How Few-Shot Prompting Works
This diagram illustrates the process of few-shot prompting. By providing examples, you enable the model to recognize patterns and understand the context, leading to a more refined and balanced output.

Deciding when to use few-shot prompting is also important. It's most effective for tasks that require a specific style or pattern but don't necessarily depend on new or private information.

Choosing the Right LLM Strategy Flowchart
This flowchart helps contextualize our choice. We are not teaching the LLM new facts (which would require Embedding-based Search) but rather a specialized style. Since this is a specialized task, few-shot prompting is an ideal strategy.

A compelling real-world application of this is using reference documents to guide generation. Imagine feeding an LLM an example of your writing to teach it your style.

Claude Skills Built Me an AI Agent Army (They Run Everything Now)

To see this in practice, watch this segment from the video 'Claude Skills Built Me an AI Agent Army.' It demonstrates how reference files—an example tweet and an example newsletter—are used to transform a short piece of content into a long-form article in a specific voice.

Watch from 23:47 to 30:30. Notice how providing an existing newsletter as a reference file (a few-shot example) allows the AI to capture the desired tone, structure, and style almost instantly. This is the exact principle we will implement in our code.


Activity: Implementing the Writer Agent

Now, let's apply these concepts in code. We'll create a reusable module for your brand voice and a new function, generateTextFromOutline, that acts as our "Writer Agent."

Step 1: Create a brandVoice.ts Module

First, let's centralize your brand voice definitions. In your project's src folder, create a new file named brandVoice.ts. This makes your brand voice portable and easy to manage.

For this exercise, let's define a brand voice that is:

  • Knowledgeable & Authoritative: Written from the perspective of an experienced engineer.
  • Clear & Concise: Avoids jargon where possible, uses short sentences.
  • Slightly Contrarian: Challenges conventional wisdom.
// src/brandVoice.ts

// Layer 1: System Role Assignment
export const systemRole = `
You are a principal software engineer and a respected thought leader in the tech community. You have 15 years of experience building scalable, event-driven systems. Your writing style is authoritative, clear, and direct. You are not a marketer; you are a builder writing for other builders. You break down complex topics into first principles and are not afraid to hold contrarian views.
`;

// Layer 2: Voice Rules
export const voiceRules = `
**Writing Rules:**
- **Tone:** Authoritative, educational, and slightly skeptical. Never use marketing fluff, hyperbole, or overly enthusiastic language ("game-changer," "revolutionary").
- **Clarity:** Use simple, direct language. Define technical terms briefly if they are not common knowledge.
- **Structure:** Average sentence length should be 15-20 words. No paragraph should exceed 4 sentences.
- **Vocabulary:** Prefer strong verbs. Avoid weak adverbs and corporate jargon (e.g., "leverage," "synergy," "utilize"). Use contractions (e.g., "it's," "don't," "you've").
- **Formatting:** Use Markdown for emphasis, lists, and code snippets where appropriate.
`;

// Layer 3: Few-Shot Examples (Contrastive)
export const fewShotExamples = `
**Style Examples (Generic vs. On-Brand):**

**Example 1: Announcing a new technology**
- **Generic:** "We are excited to announce the launch of our new cutting-edge streaming data processing engine, which leverages AI to deliver unparalleled performance and scalability."
- **On-Brand:** "The standard approach to streaming data has hit a wall. We built a new processing engine to fix it. It handles backpressure more intelligently and simplifies state management. Here's how it works."

**Example 2: Explaining a concept**
- **Generic:** "Microservices architecture is a popular architectural style that structures an application as a collection of services that are highly maintainable and testable, loosely coupled, independently deployable, and organized around business capabilities."
- **On-Brand:** "Microservices promise independence but often deliver distributed spaghetti code. The real discipline isn't breaking things apart; it's defining clean contracts and accepting the high cost of asynchronous communication."

**Example 3: A call to action**
- **Generic:** "For more information on our innovative solutions, please visit our website or contact our sales team today!"
- **On-Brand:** "This is my take on the problem. What have you seen in your own systems? Drop a comment below."
`;

Step 2: Create the generateTextFromOutline Function

Next, create a new file src/generateText.ts. This function will consume an outline from our previous lesson and the brand voice components we just defined.

// src/generateText.ts

import OpenAI from 'openai';
// Import the brand voice components
import { systemRole, voiceRules, fewShotExamples } from './brandVoice';
// Assume ContentOutline is imported from your outlining module
// import { ContentOutline } from './createOutline';

// Initialize your LLM client
const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
});

/**
 * Generates text from a content outline, applying brand voice constraints.
 * @param outline - The structured content outline from the previous step.
 * @returns The generated text as a string.
 */
export async function generateTextFromOutline(
  outline: any // Using 'any' for simplicity, but this should be your ContentOutline type
): Promise<string | null> {

  // Convert the outline object to a string format for the prompt
  const outlineString = JSON.stringify(outline, null, 2);

  const systemPrompt = `
    ${systemRole}
    
    You will be given a structured JSON outline for a piece of content. Your task is to write the full text for this content, strictly adhering to the voice, rules, and style demonstrated below.
    
    ${voiceRules}

    ${fewShotExamples}
  `;

  try {
    const response = await openai.chat.completions.create({
      model: "gpt-4-turbo",
      messages: [
        { role: "system", content: systemPrompt },
        { 
          role: "user", 
          content: `
            Based on the persona, rules, and examples I've provided, write the full content for the following outline. The output should be a single, complete piece of text in Markdown format. Do not output anything else.

            **Content Outline:**
            \`\`\`json
            ${outlineString}
            \`\`\`
          `
        }
      ],
      temperature: 0.7, // A bit of creativity, but still grounded
    });

    const content = response.choices[0].message.content;
    if (!content) {
      throw new Error("Empty response from LLM.");
    }
    
    console.log(`Successfully generated text for platform: ${outline.platform}`);
    return content;

  } catch (error) {
    console.error(`Error during text generation:`, error);
    return null;
  }
}

Now you have a generateTextFromOutline function that is hard-coded with your specific brand voice. By feeding it the outlines you generated in the previous lesson, you can now produce stylized, on-brand content.


Conclusion

In this lesson, you have taken a massive step toward creating truly autonomous and high-quality content. You've learned that controlling an LLM's style is an engineering problem that can be solved with systematic prompt design.

Key Takeaways:

  • Generic AI voice is a solved problem: You can achieve a consistent brand voice without fine-tuning a model.
  • The Layered Prompt Architecture is key: Combining a System Role, Measurable Rules, and Few-Shot Examples provides robust control over the LLM's output.
  • Contrastive examples are highly effective: Showing the LLM what not to do (Generic) alongside what to do (On-Brand) sharpens its understanding of your style.
  • Modularize your brand voice: Storing your brand voice definitions in a separate module (brandVoice.ts) makes your system cleaner, more maintainable, and easier to adapt.

Preview of the next lesson:
Now that we have a general-purpose "Writer Agent," our next step is to specialize its output for each platform. In the next lesson, "Design prompts that generate LinkedIn posts with effective hooks and professional structure," we will refine our text generation process to create short-form posts for LinkedIn, focusing on crafting compelling hooks and structuring content for professional engagement.