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.