ap.Abhishek Patel

Search

Search notes, essays, projects, the library and the AI course. Use arrow keys to choose and Enter to open.

Lesson 1 of 6 30 min

Summarisation, translation and tone control

Turn summaries, translations and tone rewrites from demos into dependable tools by naming the reader, fixing what must not change, and checking numbers and protected terms in code.

Words in this lessonSummarisation · Extractive summary · Abstractive summary · Map-reduce · Machine translation · Back-translation · Tone control
Summarisation
Turning a long text into a shorter one that keeps what matters to a particular reader. Like a colleague who reads the whole report and tells you the three things you need before your meeting.
Extractive summary
A summary made by picking the most important sentences from the source, word for word. Like highlighting the key sentences in a book with a marker.
Abstractive summary
A summary written in new words that capture the meaning of the source. Like retelling a film to a friend in your own words.
Map-reduce
Processing a large input by handling each piece separately, then combining the results. Like six people each reading fifty reviews and a seventh combining their notes.
Machine translation
Converting text from one language to another by computer. Like a bilingual colleague who is fluent but needs to be told which brand names never to change.
Back-translation
Translating a translation back into the original language to check that the meaning survived. Like repeating an order back to the customer to make sure you heard it right.
Tone control
Rewriting text so it sounds a particular way while keeping its facts the same. Like adjusting the bass and treble on a song without changing the lyrics.
On this page
  1. Arjun's three one-liners
  2. Three questions every editor asks
  3. Following one complaint through all three tasks
  4. Opening the hood: how each rewrite goes wrong
  5. Summaries: extractive, abstractive and the long tail
  6. Translation: the words that must not move
  7. Tone: dials, not adjectives
  8. Building the toolkit, one function at a time
  9. Where it breaks
  10. Try it yourself
  11. Common mistakes
  12. Recap
  13. Go deeper

Meera arrived at the tech corner with a sticky note and three requests, each underlined twice.

One. “Every Monday I read last week’s reviews. About three hundred of them. It takes my whole morning, four hours, and by the end I can’t remember what was in the first fifty. Can the computer give me the gist?”

Two. “Half our WhatsApp customers write in Marathi or Hindi. The Diwali menu, forty-two items, is only in English. I want it in all three languages by Friday.”

Three. She held up a printout. A store manager had replied to a customer: We already told you, refunds take 7 days. Please stop emailing. “Kavita says about one reply in eight from the stores sounds like this. Can it make us sound like ourselves, but kind?”

Arjun grinned. “That’s three lines of code each.”

Priya, without looking up from her screen, said, “That’s three lines of code each to get a demo. Let’s make them good enough that Meera stops checking them.”

Important

The idea in one sentence: Summarisation, translation and tone control are all rewriting tasks, and they go from demo to dependable when you tell the model who the reader is, how long it should be, and what must stay exactly the same, and then check that in code.

Arjun’s three one-liners

Arjun had all three running before lunch. Each was a single instruction plus the text:

def summarise(reviews: str) -> str:
    return ask(f"Summarise these reviews.\n\n{reviews}")

def translate(text: str, language: str) -> str:
    return ask(f"Translate to {language}.\n\n{text}")

def make_nicer(reply: str) -> str:
    return ask(f"Make this nicer.\n\n{reply}")

(ask is the small helper from Module 02 that sends one user message and returns the reply text.)

The results looked impressive at a glance. Meera read them properly.

The summary was a fluent 400 words: “Customers generally enjoyed the festive range, with particular praise for the kaju katli. Some customers raised concerns about delivery times…” It was accurate, as far as it went. It did not mention review #212, in which a customer said her son’s lips swelled after eating a “nut-free” coconut barfi. One review in three hundred. The one that mattered most.

The translation of the menu into Marathi turned “Black Forest Cake” into “काळे जंगल केक”, literally “black jungle cake”. It also translated “Crumb & Co.” into a Marathi phrase meaning “breadcrumbs and company”, and wrote the prices in Devanagari numerals, so ₹950 became ₹९५०, which the billing team’s system could not read.

The nicer reply said: “We’re so sorry for the wait! We’ll make sure your refund is processed right away.” Lovely. And false. Refunds take seven working days; nobody can do it “right away”.

“Each one is nearly right,” Arjun said, “and each one is wrong in a way that could actually hurt.”

“Good. Now tell me what the three failures have in common.”

Three questions every editor asks

Arjun stared at the three outputs. “The summary dropped something important. The translation changed things that should’ve stayed the same. The rewrite changed a fact.”

“Before a newspaper sub-editor touches a reporter’s story, what do they want to know?”

“Uh. Who’s reading it?”

“What else?”

“How much space they have. A column? A paragraph?”

“And?”

He thought about it. “What they’re not allowed to change. Quotes. Names. Numbers.”

Priya wrote the three on the whiteboard:

  1. Who is the reader, and what will they do with it?
  2. How long, and in what shape?
  3. What must stay exactly as it is?

“Your three prompts answered none of them. So the model answered them for you, with the most typical answer. A typical summary skips rare things. A typical translation translates everything. A typical ‘nicer’ reply promises what customers want to hear.”

All three tasks are forms of rewriting: producing a new text from an existing one, under constraints. Summarisation makes it shorter while keeping what matters. Machine translation moves it into another language while keeping the meaning. Tone control changes how it sounds while keeping the facts. The same three questions apply to all of them, and so does the same danger: the model is fluent enough that a rewrite reads well whether or not it is faithful.

Following one complaint through all three tasks

To see the three questions in action, Priya picked a single real message and sent it through every task. On the Wednesday after Diwali, Mrs. Joshi wrote to Crumb’s WhatsApp line in Marathi:

मी दिवाळीसाठी ड्रायफ्रूट हॅम्पर मागवला होता. तो लक्ष्मीपूजनाच्या दिवशी न येता भाऊबीजेला आला. चकली मऊ झाली होती. खूप निराशा झाली. ऑर्डर नं. 4471.

Step 1: translate it for the team. The store team in Aundh reads English best. The translation brief answered the three questions: the reader is the store team; same length; keep the order number, product names and festival names exactly.

Result: “I had ordered a dry-fruit hamper for Diwali. Instead of arriving on Lakshmi Pujan day, it came on Bhau Beej. The chakli had gone soft. Very disappointed. Order no. 4471.”

Notice what stayed: “chakli”, “Lakshmi Pujan”, “Bhau Beej” and “4471”. Translating “chakli” as “spiral rice snack” would have been accurate and useless to a Pune bakery team.

Step 2: summarise it for the right reader. The delivery lead does not need the whole message; she needs to know what her team owns. Brief: reader is the delivery lead; one line; lead with the delivery fact.

Result: “Order 4471 (Diwali hamper) delivered on Bhau Beej, three days after the requested Lakshmi Pujan date; chakli also soft.”

That summary would be different for the recipe team (“chakli soft in hamper, order 4471”) and for Meera’s weekly report (one tally mark under “late hampers”). Same message, three readers, three summaries.

Step 3: draft a reply in Crumb’s tone. Brief: warm, plain, respectful; acknowledge both problems specifically; do not promise compensation, because a teammate decides that after checking with the delivery partner; under 80 words.

Draft (in English, for the record): “Mrs. Joshi, I’m so sorry your hamper arrived on Bhau Beej instead of in time for Lakshmi Pujan, and that the chakli wasn’t crisp. That’s not the Diwali we wanted for you. A teammate is checking order 4471 with our delivery partner and will message you by tomorrow evening with next steps. Thank you for telling us. Team Crumb”

Step 4: translate the reply back into Marathi with the same glossary and keep-list, so the customer is answered in her own language.

Step 5: check, in code. A short function confirmed that “4471” appeared in every output, that no output contained the words “refund”, “voucher” or “free” in any language list Arjun maintained, and that the Marathi reply used Western digits for the order number. Then the Marathi reply was translated back into English by a separate call, and Arjun compared it with the English draft. They matched in meaning.

The cost. Five calls on a small model, about 1,600 input and 500 output tokens in total. At illustrative prices of 2 per million output, that is about $0.0014, or ₹0.12, for the whole chain. Kavita estimated the same work by hand at ten minutes.

Note

Pause and think. In step 5, the back-translation matched the English draft. Does that prove the Marathi reply is good?

Show the answer

No. It is good evidence that the meaning survived, which catches the worst errors: a missing sentence, a wrong number, a dropped apology. But back-translation cannot judge whether the Marathi sounds natural, polite in the right way, or slightly odd to a native speaker. A translation can be accurate and still stiff. For routine replies, back-translation plus code checks is a sensible bar; for anything published, like the Diwali menu or an allergen label, a fluent human should read it.

Opening the hood: how each rewrite goes wrong

Each task has its own characteristic failure, and knowing it tells you what to check.

Summaries: extractive, abstractive and the long tail

There are two broad kinds of summary. An extractive summary picks the most important sentences from the source and keeps them word for word. It cannot invent anything, but it reads choppily. An abstractive summary writes new sentences that capture the meaning. It reads naturally, and it is what LLMs produce by default, but it can drift from the source or blend separate facts together.

The deeper problem with Meera’s summary is the long tail. A summary, by design, keeps what is common and drops what is rare. One allergy report in three hundred reviews is, statistically, noise. To Meera it is the most important line in the week. No amount of “please be thorough” fixes this reliably, because “keep the rare things” contradicts “make it short”. The robust fix is to detect critical items separately, with a keyword check or a dedicated classifier, and list them outside the summary.

Then there is length. Three hundred reviews at about 60 tokens each is 18,000 tokens, which fits comfortably in a modern context window. But a year of reviews, or the 200-page operations handbook, may not fit, and even when text fits, quality drops on very long inputs. The standard pattern is map-reduce:

flowchart LR
    A["300 reviews"] --> B["Split into 6 batches of 50"]
    B --> C1["Summarise batch 1"]
    B --> C2["Summarise batch 2"]
    B --> C3["... batch 6"]
    C1 --> D["Combine 6 batch summaries"]
    C2 --> D
    C3 --> D
    D --> E["Final summary for Meera"]

Map: summarise each batch on its own; these calls can run in parallel. Reduce: summarise the summaries. For Meera’s week: six batch calls of about 3,000 input tokens each, producing about 150 tokens each; then one reduce call over 900 tokens. More calls, but each one is short and focused, and the batch summaries can carry counts (“7 of 50 mention late delivery”) that the reduce step adds up honestly.

Translation: the words that must not move

LLMs translate well between widely used languages because they were trained on text in many languages at once. For Hindi and Marathi the quality is good for everyday text, though less polished than English to French, because there is less training text. The errors that matter in a business are rarely grammar. They are things that should not have been translated at all: brand names, product names with local names already (modak, nankhatai, chakli), prices, weights, order numbers and fixed safety wording.

There is also a cost quirk. Tokenizers are built mostly from English text, so the same sentence in Devanagari script often takes two to four times as many tokens as in English, depending on the tokenizer. Translating the 42-item menu into Marathi costs more, and fills more context, than the English original suggests.

Note

Pause and think. The summary of 300 reviews left out the single allergy report. Arjun’s first instinct is to add “Never leave out allergy mentions” to the summary prompt. Why is that better than nothing, but not good enough?

Show the answer

It will catch most cases, because you have made allergy mentions part of what “matters”. But the model still has to notice a single sentence among 18,000 tokens, worded in ways you cannot predict (“lips swelled”, “had to use his EpiPen”, “rashes after the barfi”), while also squeezing everything into 250 words. Sometimes it will miss one, and you will not know. A separate check that looks at every review on its own, one small call or keyword pass per review, does not have to compete with the summary for attention, and its result can be listed in full.

Tone: dials, not adjectives

“Make this nicer” has two problems. “Nicer” means different things to different people, and the easiest way for a model to make a message nicer is to give the reader what they want, which often means changing the facts. Two techniques help.

First, describe tone as a few explicit dials rather than one adjective:

Formality: 2/5   Warmth: 4/5   Firmness: 3/5   Length: under 80 words

The numbers are fuzzy to the model, but far less fuzzy than “nicer”, and they give Crumb’s team a shared vocabulary: store replies should be 2/4/3; wholesale replies 4/3/3.

Second, list the facts that must survive and check them in code afterwards. Numbers are the easiest: every number and rupee amount in the original should appear in the rewrite.

Improving writing (fixing grammar, tightening, clarifying) is tone control’s sibling with the same risk. Ask for the improved text and a short list of changes (“before -> after (reason)”), so a person can review in seconds rather than rereading both versions.

Building the toolkit, one function at a time

Step 1: one rewriting core with standing rules. Every task shares the same guardrails, so they live in one place. Install with uv add openai python-dotenv.

import os
from dotenv import load_dotenv
from openai import OpenAI

load_dotenv()
client = OpenAI()
MODEL = os.getenv("OPENAI_MODEL", "gpt-5-mini")  # model names change; see the provider's models page

STANDING_RULES = ("You rewrite text for Crumb & Co., a family bakery in Pune. "
                  "Never add facts, promises, dates or numbers that are not in the source. "
                  "Keep all numbers in Western digits (0-9). Return only the rewritten text.")

def rewrite(text: str, brief: str) -> str:
    resp = client.chat.completions.create(model=MODEL, messages=[
        {"role": "system", "content": STANDING_RULES},
        {"role": "user", "content": f"{brief}\n\n<text>\n{text}\n</text>"},
    ])
    return resp.choices[0].message.content.strip()

Step 2: summaries with a reader, a length and map-reduce.

def summarise(texts: list[str], reader: str, max_words: int, batch: int = 50) -> str:
    batches = [texts[i:i + batch] for i in range(0, len(texts), batch)]
    partials = [rewrite("\n".join(b),                                  # map: one call per batch
                        f"Summarise these {len(b)} reviews as bullet points with counts "
                        "(e.g. '7 of 50 mention late delivery'). Quote nothing.")
                for b in batches]
    return rewrite("\n\n".join(partials),                              # reduce: combine the partials
                   f"Combine these partial summaries for {reader}. Add up the counts. "
                   f"Under {max_words} words: a one-line verdict, top three complaints "
                   "with counts, top two praises with counts.")

ALLERGY_WORDS = ["allerg", "swell", "rash", "epipen", "reaction", "anaphyl", "hives"]

def critical_items(texts: list[str]) -> list[str]:
    """Checked separately, on every review, so the summary can never drop them."""
    return [t for t in texts if any(w in t.lower() for w in ALLERGY_WORDS)]

Run it on last week’s reviews and print both: the summary, then the list of critical items under its own heading. Meera’s Monday report now always ends with “Allergy and illness mentions (2): …” in full. In the next lesson you will replace the keyword list with a proper classifier.

Step 3: translation with a glossary and a keep-list.

KEEP = ["Crumb & Co.", "Black Forest", "Red Velvet", "chakli", "modak", "nankhatai",
        "kaju katli", "Lakshmi Pujan", "Bhau Beej"]

def translate(text: str, language: str, glossary: dict[str, str]) -> str:
    fixed = "\n".join(f'- "{en}" -> "{tr}"' for en, tr in glossary.items())
    brief = (f"Translate into {language}. Keep these exactly as written, untranslated: "
             f"{', '.join(KEEP)}.\nUse these approved translations:\n{fixed}\n"
             "Keep prices, weights and order numbers exactly as in the source. "
             "Tone: warm and polite, suitable for a family bakery.")
    return rewrite(text, brief)

def back_check(original_en: str, translated: str) -> str:
    """Translate back to English with a fresh call, for a human or a test to compare."""
    return rewrite(translated, "Translate into English, as literally as possible.")

The glossary holds wording Crumb has agreed once, checked by a fluent speaker: the Marathi for “eggless”, the exact allergen warning. The model should never improvise those.

Step 4: tone control with a fact check in code.

import re

def numbers_in(text: str) -> set[str]:
    return set(re.findall(r"\d+", text))   # every run of digits: amounts, days, order IDs

def adjust_tone(reply: str, formality: int, warmth: int, firmness: int, max_words: int) -> str:
    brief = (f"Rewrite this customer reply in Crumb's voice. Formality {formality}/5, "
             f"warmth {warmth}/5, firmness {firmness}/5, under {max_words} words. "
             "Keep every fact exactly. Do not add promises or follow-up actions "
             "that are not in the original.")
    new = rewrite(reply, brief)
    missing = numbers_in(reply) - numbers_in(new)
    if missing:
        raise ValueError(f"Rewrite dropped or changed numbers: {missing}")
    return new

print(adjust_tone("We already told you, refunds take 7 days. Please stop emailing.",
                  formality=2, warmth=4, firmness=3, max_words=80))

Arjun’s run printed: “I’m sorry the wait has been frustrating. Your refund has been approved and takes up to 7 working days to reach your account. If it hasn’t arrived by then, please reply here. Team Crumb”. The “7” survived, so the check passed. If the model had written “a week”, the check would have raised an error, and the reply would go to a person.

Where it breaks

The toolkit went live on Monday. By Friday it had found new ways to surprise everyone.

The invented trend. One weekly summary said “many customers complained about the new packaging”. Three had. The fix was already in step 2, and Arjun had briefly removed it: ask for counts at the map stage, and make the reduce step add them. “Many” is an opinion; “3 of 287” is a fact.

The helpful addition. A tone rewrite produced: “…and as a thank-you for your patience, we’ve added a small treat to your next order.” No numbers changed, so the code check passed. Promises without numbers slip through. Arjun added a second check for promise words (“free”, “complimentary”, “treat”, “voucher”, “discount”) in English, Hindi and Marathi, and a list of phrases for Kavita to review.

The glossary that was not used. Twice, the Marathi menu came back with “Black Forest” translated anyway, on items deep in the 42-item list. Long inputs dilute instructions. Translating in batches of ten items, with the keep-list repeated in every call, fixed it, and a code check now asserts every keep-list word that appears in the English also appears in the translation.

The register that was off. A Marathi-speaking customer replied to one message: “Why is the bakery talking to me like a government office?” The translation was correct and very formal. Tone dials apply to translations too: the brief now says “conversational, polite Marathi, as a shopkeeper would speak to a regular customer”.

Warning

Allergen and food-safety wording must never be freshly generated in translation. Store approved translations of every warning, written or checked by a fluent speaker, and insert them in code. A fluent-sounding but wrong allergen warning is worse than none.

Try it yourself

Take this review and produce three outputs with three separate briefs:

“Ordered the Diwali hamper for my in-laws in Kothrud. Packaging was gorgeous, the kaju katli was fresh, but the chakli was soggy and it arrived on Bhau Beej instead of Lakshmi Pujan like I asked. Order 5520. Bit embarrassing honestly.”

  1. A one-line summary for the delivery lead.
  2. A Hindi translation that keeps “Crumb”, “kaju katli”, “chakli”, the festival names and “5520” untouched.
  3. A reply from Crumb with formality 2/5, warmth 5/5, firmness 2/5, no promise of compensation. Run it through adjust_tone so the number check applies.
Show the answer
  1. Something like: “Order 5520, Diwali hamper to Kothrud, arrived on Bhau Beej instead of the requested Lakshmi Pujan; chakli soggy, rest of hamper good.” It leads with what the delivery lead owns (the date) and keeps the product issue as context.
  2. Check that every protected word and the number appear unchanged. If you do not read Hindi, run back_check and compare meaning. Also check the digits are Western: “5520”, not “५५२०”.
  3. A good reply thanks them, mentions the packaging and kaju katli they liked, apologises specifically for the late arrival and the soggy chakli, includes order 5520, and says a teammate will follow up. If it offers a refund, a voucher or “a little something”, your brief needs to forbid follow-up actions more firmly, and a promise-word check should catch it.

Common mistakes

  • No named reader. “Summarise” without a reader produces a summary for nobody. Name who will read it and what they will do.
  • Trusting summaries with rare, critical items. Detect those separately, on every item, and list them in full.
  • Vague quantities. “Many customers” hides the real number. Ask for counts.
  • Translating everything. Keep a do-not-translate list and a glossary of approved wording.
  • Letting tone edits change facts. Say facts must not change, then check numbers and promise words in code.
  • No length limit. Models drift long. Give a word count.

Recap

  • Summarisation, translation and tone control are all rewriting tasks; each brief should name the reader, the length and shape, and what must not change.
  • Summaries keep the common and drop the rare, so detect critical items separately; use map-reduce, with counts, for long inputs.
  • Translations need a keep-list and approved wording for fixed phrases; back-translation checks meaning but not naturalness.
  • Tone control works best with explicit dials, plus code checks that numbers and promises did not change.
  • Faithfulness is the real risk in every rewrite, because fluent text reads well whether or not it is true.

The following Monday, Meera finished her review report before her chai went cold. “Fifteen minutes,” she told Arjun. “Explain to me why I should trust it.”

“Because it doesn’t try to do everything in one go,” Arjun said. “For summaries, I tell it who’s reading and ask for real counts, not ‘many’. Anything about allergies is checked separately, on every single review, and listed in full at the bottom, so the summary can’t lose it. For translation, there’s a list of words it must never touch, and our allergy warnings are pre-approved text, not generated. For replies, my code checks that no number changed and nothing was promised. If anything fails, it goes to Kavita.”

Meera nodded. Then she turned her laptop round: the support inbox, 380 unread. “The summaries tell me what went wrong last week. What I need is for the right person to know the moment it happens. Right now, Kavita reads every one of these and forwards them by hand.”

Go deeper

Check your understanding

3 quick questions
1. A weekly summary of 300 reviews leaves out the one review reporting an allergic reaction. What is the most robust fix?
2. Which item should usually NOT be translated when localising Crumb's menu into Marathi?
3. A tone rewrite of "Refunds take 7 days" comes back as "Your refund will arrive within a week, and we have added a treat to your next order." What should your checks catch?