Skip to main content

Module 6 — Controlling style, length and tone

Module 5 turned the four extracted fields into a validated JSON object. The support system that consumes them also wants a one-line customer-facing acknowledgement to send back automatically. This new output is prose, not fields, and the same prompt-engineering discipline applies: measurable constraints beat vague adjectives, every time.

Vague adjectives fail silently

The tempting first draft is:

SYSTEM = """... After the JSON, write a short, polite, professional
acknowledgement to the customer."""

Ten runs on the same email produce ten different lengths, three different registers, and at least one that opens with "Dear valued customer" — a phrase you probably wanted to avoid. The words short, polite and professional have no scale that the model consistently applies.

The pattern: any adjective without an operational definition is a wish, not an instruction. Vague requests produce variable answers because the model has no anchor to know which of several plausible interpretations you meant.

Measurable constraints work

Replace each adjective with something the model can execute mechanically:

SYSTEM = """... After the JSON, write an acknowledgement to the
customer following these constraints:
- Two sentences, no more.
- No greeting, no sign-off.
- First sentence names the product and the issue.
- Second sentence commits to a next step within one business day.
- Do not use the words "unfortunately", "kindly" or "valued customer".
"""

Every constraint above can be checked automatically on the output: sentence count with nltk, first-sentence content with a substring test, banned-word list with a regex. That means the same rule that guides the model also serves as an offline validator, and the two can never drift.

The general principle: prefer constraints that are testable in a unit test. If you cannot write a Python line that checks whether the constraint was respected, the model cannot reliably respect it either.

Length: sentences, not words

Everyone reaches for word counts first, and everyone is disappointed. "Answer in exactly 40 words" is one of the least reliable instructions you can give a language model. Tokens are not words, the model does not count them internally, and the answer varies wildly.

Sentence counts are dramatically more reliable, because a sentence is a unit the model tracks naturally:

InstructionAdherence rate on 100 testsMedian deviation
"About 40 words"around 30 %±15\pm 15 words
"Exactly 40 words"around 45 %±8\pm 8 words
"Two sentences"around 90 %±0\pm 0 sentences
"Two sentences, each between 10 and 20 words"around 85 %±1\pm 1 word per sentence

Numbers vary by model and task, but the ranking is stable across providers. Length in sentences is cheap to enforce and reliably followed; length in words is expensive to enforce and only partially followed.

Tone: examples beat descriptors

Tone descriptors — "warm", "professional", "empathetic" — are like adjectives for length: interpreted differently every call. The reliable route is to show the tone with two or three sample answers, exactly as few-shot in module 3:

TONE_EXAMPLES = [
("Product X broke on day two.",
"We're sorry your Product X failed so quickly. A replacement is on its way and you'll have tracking within 24 hours."),
("The kettle is fine, I just wanted a manual.",
"Thanks for the note. The kettle manual is attached, and you'll find PDFs of every model in the support portal."),
]

Two well-chosen examples fix the tone at negligible cost, because they are cached across calls. A single paragraph describing the tone in the system message rarely matches them for consistency.

Tone examples must represent the whole range

If both examples are for high-severity issues, the tone bleeds into low-severity replies as well, producing overly grave acknowledgements for a request for a manual. Cover the range — one grave, one neutral, one light — the same way module 3 asked for contrasting labels.

Brand voice across a library

A support platform rarely has one prompt. It has ten or twenty, and if each defines tone in its own words, replies drift across surfaces: warm on refunds, curt on shipping, formal on returns. The fix is a shared style module referenced by every prompt:

STYLE = """Brand voice: direct, warm, no jargon.
- One idea per sentence.
- No exclamation marks.
- No "please" at the start of a sentence.
- Refer to the customer by their first name if known, "you" otherwise.
- Numbers use figures (2 days) except at the start of a sentence.
"""

def build_system(task_specific: str) -> str:
return STYLE + "\n" + task_specific

Every prompt now inherits the same style, and a change to the brand voice ripples across the whole library at once. This is what module 10 formalises as a prompt template with variables.

The special case of very short outputs

For outputs of one or two sentences, models sometimes trade fluency for brevity in awkward ways: dropped articles, missing punctuation, or telegraphic style ("Refund. Sent."). Two counter-measures:

  • Give the exact target range as a compound constraint: "one full sentence, complete with subject and verb, 12 to 25 words".
  • Provide a short example rather than a long one. The model matches the length of the example more than the length of the instruction. If you show a 30-word example, expect a 30-word answer.

Cost and latency of longer answers

Every output token is billed and adds latency. On the running case, a two-sentence acknowledgement costs about 4040 output tokens; a "detailed friendly reply" would cost around 200200. At a million calls per month and 0.600.60 per million output tokens, that is roughly:

\approx 96 \text{ dollars per month.}$$ Trivial in isolation, real once ten prompts of similar magnitude accumulate. Latency is often the larger concern: at $50$ ms per token, $200$ tokens take $10$ seconds versus $2$ seconds for $40$. On a live chat, that is the difference between usable and not. :::tip[Constraints reduce cost and improve quality at the same time] "Two sentences" saves tokens and produces more consistent output. "Detailed" costs tokens and produces less consistent output. When constraints and cost pull in the same direction, take the deal. ::: ## In summary - Replace **vague adjectives** with constraints you can check in a Python line: sentence count, banned words, mandatory structure. - Prefer **length in sentences** over length in words; sentence counts are followed reliably, word counts are not. - For **tone**, two or three well-chosen examples beat paragraphs of descriptors — and share them across prompts through a common style module. - **Shorter constrained answers** cost less, arrive faster and vary less across calls; when the constraint and the bill agree, take it. Next module: writing prompts in the language of the answer, and the pitfalls specific to English that a naive translation produces.