TAI BUI
Back to curriculum
BuildPython

Text Summarization

Extractive tells you what the document said. Abstractive tells you what the author meant. Different tasks, different pitfalls.

TIME: ~75 minutesPREREQUISITES: Phase 5 · 02 (BoW + TF-IDF), Phase 5 · 11 (Machine Translation)

Learning Objectives

  • Explain the behavioral difference between extractive and abstractive summarization, and the specific failure mode each one owns.
  • Implement TextRank from scratch, scoring sentences by running a PageRank-style iteration over a sentence-similarity graph.
  • Generate abstractive summaries with a pretrained BART model, evaluate them with ROUGE, and place ROUGE against the 2026 metric stack (BERTScore, MoverScore, G-Eval) that goes beyond it.
  • Name the canonical abstractive hallucination types (entity swap, number drift, polarity flip, fact invention) and decide when a factuality check has to sit in front of an abstractive summarizer before it ships.

The Problem

A 2,000-word news article lands in your feed. You need 120 words that capture it, and you have two options: pick the three sentences that carry the most weight (extractive), or rewrite the whole thing in new words (abstractive). Both get called summarization. They are not the same problem.

Extractive summarization is a ranking problem. Score every sentence, return the top-k, done. Because the output is lifted verbatim, it's always grammatical. The risk is that the content you need is scattered across sentences that never made the cut.

Abstractive summarization is a generation problem: a transformer reads the input and produces new text conditioned on it. The output reads fluently and compresses well, but it can hallucinate facts nobody wrote. Confident fabrication is the risk you're actually managing.

This lesson builds both, and hands you the specific failure mode each one owns.

Warm-up0/3
1. You skim a long article and want to give someone its gist. One option is copying the three sentences that matter most, word for word. The other is writing a two-sentence paraphrase from memory. Which approach is more likely to accidentally state something the article never actually said?Warm-up
2. Before any formal scoring: if your written summary shares many of the same words and phrases with a summary a trusted expert already wrote, is that generally a sign of a better or worse summary?Warm-up
3. A text is turned into a vector with one slot per vocabulary word, each holding how many times that word occurs, and word order is thrown away. What is this representation called?Warm-up
Check: The Problem0/4
1. What does an extractive summarizer return?Define
2. What is abstractive summarization?Define
3. Extractive output is always grammatical because it is lifted verbatim. What risk does it still carry?Explain
4. Why is abstractive summarization riskier than extractive when facts matter?Explain

The Concept

Extractive TextRank vs abstractive transformer

Extractive. Treat the article as a graph: nodes are sentences, edges are similarity scores. Run PageRank (or something close to it) over that graph so a sentence's score reflects how connected it is to everything else, then take the highest scorers as your summary. The canonical implementation is TextRank (Mihalcea and Tarau, 2004).

Abstractive. Fine-tune a transformer encoder-decoder (BART, T5, Pegasus) on document-summary pairs. At inference, the model reads the document and generates the summary token by token, attending back to the source through cross-attention. Pegasus stands out here: its gap-sentence pretraining objective (mask out whole sentences during pretraining, then train the model to regenerate them) makes it strong at summarization with little to no fine-tuning.

Evaluation runs on ROUGE (Recall-Oriented Understudy for Gisting Evaluation). ROUGE-1 and ROUGE-2 score unigram and bigram overlap; ROUGE-L scores the longest common subsequence. Higher is better, though the scale is compressed: 40 ROUGE-L reads as "good," 50 as "exceptional." Report all three, the way every paper does, using the rouge-score package.

Check: The Concept0/5
1. How does TextRank score sentences in extractive summarization?Define
2. What does ROUGE measure?Define
3. Why does a sentence that is similar to many other sentences tend to get a high TextRank score?Explain
4. What is the gap-sentence pretraining objective that makes Pegasus strong at summarization?Explain
5. How does ROUGE-L differ from ROUGE-1 and ROUGE-2?Explain

Build It

Step 1: TextRank (extractive)

python
import math
import re
from collections import Counter
 
 
def sentence_split(text):
    return re.split(r"(?<=[.!?])\s+", text.strip())
 
 
def similarity(s1, s2):
    w1 = Counter(s1.lower().split())
    w2 = Counter(s2.lower().split())
    intersection = sum((w1 & w2).values())
    denom = math.log(len(w1) + 1) + math.log(len(w2) + 1)
    if denom == 0:
        return 0.0
    return intersection / denom
 
 
def textrank(text, top_k=3, damping=0.85, iterations=50, epsilon=1e-4):
    sentences = sentence_split(text)
    n = len(sentences)
    if n <= top_k:
        return sentences
 
    sim = [[0.0] * n for _ in range(n)]
    for i in range(n):
        for j in range(n):
            if i != j:
                sim[i][j] = similarity(sentences[i], sentences[j])
 
    scores = [1.0] * n
    for _ in range(iterations):
        new_scores = [1 - damping] * n
        for i in range(n):
            total_out = sum(sim[i]) or 1e-9
            for j in range(n):
                if sim[i][j] > 0:
                    new_scores[j] += damping * sim[i][j] / total_out * scores[i]
        if max(abs(s - ns) for s, ns in zip(scores, new_scores)) < epsilon:
            scores = new_scores
            break
        scores = new_scores
 
    ranked = sorted(range(n), key=lambda k: scores[k], reverse=True)[:top_k]
    ranked.sort()
    return [sentences[i] for i in ranked]

Two things worth flagging. The similarity function uses log-normalized word overlap, the original TextRank variant; cosine similarity over TF-IDF vectors works just as well. The damping factor of 0.85 and the iteration count are both standard PageRank defaults, carried over unchanged.

Step 2: abstractive with BART

python
from transformers import pipeline
 
summarizer = pipeline("summarization", model="facebook/bart-large-cnn")
 
article = """(long news article text)"""
 
summary = summarizer(article, max_length=120, min_length=60, do_sample=False)
print(summary[0]["summary_text"])

BART-large-CNN is fine-tuned on the CNN/DailyMail corpus, so it produces news-style summaries straight out of the box. Outside news (scientific papers, dialog, legal text), reach for the matching Pegasus checkpoint, or fine-tune on your own data instead.

Step 3: ROUGE evaluation

python
from rouge_score import rouge_scorer
 
scorer = rouge_scorer.RougeScorer(["rouge1", "rouge2", "rougeL"], use_stemmer=True)
scores = scorer.score(reference_summary, generated_summary)
print({k: round(v.fmeasure, 3) for k, v in scores.items()})

Always turn stemming on. Skip it and "running" and "run" count as different words, so ROUGE quietly undercounts overlap that's actually there.

Beyond ROUGE (2026 summarization eval)

ROUGE has carried summarization evaluation for twenty years, and by 2026 it's not enough on its own. A large-scale meta-analysis of NLG papers backs that up:

  • BERTScore (contextual embedding similarity) gained ground through 2023 and now shows up alongside ROUGE in most summarization papers.
  • BARTScore treats evaluation as generation: it scores a summary by how likely a pretrained BART model assigns to it, given the source.
  • MoverScore (Earth Mover's Distance over contextual embeddings) took the top spot in 2025 summarization benchmarks, because it captures semantic overlap that ROUGE misses.

Those three all score semantic overlap: how close the summary reads to a trusted reference. A second cluster targets faithfulness directly, asking whether the summary said something true rather than something that merely reads well.

  • FactCC and QA-based faithfulness were the standard 2021 to 2023, largely replaced now by G-Eval: a GPT-4 prompt chain that scores coherence, consistency, fluency, and relevance with chain-of-thought reasoning.
  • G-Eval and similar LLM-judge approaches land within about 80% of human judgment when the rubric is well designed.

For production, report ROUGE-L for legacy comparison, BERTScore for semantic overlap, and G-Eval for coherence and factuality, calibrated against 50 to 100 human-labeled summaries.

Step 4: the factuality problem

Abstractive summaries are prone to hallucination. Extractive summaries carry far less of that risk, since the output is lifted verbatim from the source, though they can still mislead if a sentence gets pulled out of context, goes stale, or gets quoted out of order. That gap is the single biggest reason production systems still lean extractive for compliance-adjacent content.

Name the hallucination types so you know what to look for:

  • Entity swap. Source says "John Smith." Summary says "John Brown."
  • Number drift. Source says "25,000." Summary says "25 million."
  • Polarity flip. Source says "rejected the offer." Summary says "accepted the offer."
  • Fact invention. Source does not mention the CEO. Summary says the CEO approved.

A few evaluation approaches actually catch these:

  • FactCC. A binary classifier trained on entailment between source sentence and summary sentence, predicting factual or not.
  • QA-based factuality. Ask a QA model questions whose answers live in the source. If the summary supports different answers, flag it.
  • Entity-level F1. Compare named entities in source against summary. Entities that show up only in the summary are suspect by default.

For anything user-facing where factuality actually matters (news, medical, legal, financial), extractive stays the safer default. If you're shipping abstractive, put a factuality check in the loop, not an afterthought.

Check: Build It0/19
1. What does factuality mean when evaluating a summary?Define
2. In summarization, what is a hallucination?Define
3. What is G-Eval, and what does it score?Define
4. Which of these is an abstractive hallucination type to monitor for?Define
5. Why enable stemming when computing ROUGE?Explain
6. How does BARTScore evaluate a summary?Explain
7. How do the faithfulness metrics (FactCC, QA-based checks, G-Eval) differ from semantic-overlap metrics like BERTScore and MoverScore?Explain
8. Which evaluation is built to detect summary hallucinations by classifying whether a source sentence supports a summary sentence?Explain
9. Using the `similarity` function from the TextRank code, what does `similarity("the cat sat", "the cat ran")` return, to two decimals? (Counters of lowercased words, intersection size over log(len(w1)+1) + log(len(w2)+1), natural log.)Apply
10. `textrank(text, top_k=3)` is called on a text that splits into exactly 3 sentences. What happens?Apply
11. In `textrank`, the three highest-scoring sentences are at indices 4, 0, and 2, in that score order. In what order does the function return them?Apply
12. With `use_stemmer=True`, what is the ROUGE-1 fmeasure for reference "run fast" and generated text "running fast"? (Stemming maps "running" to "run".)Apply
13. A source says "revenue of 25,000" and the summary says "revenue of 25 million". Which hallucination type is this?Apply
14. A generated summary has a high ROUGE-L against the reference, but it says the board "accepted the offer" where the source says "rejected the offer". What is the best diagnosis?Analyze
15. An extractive summary quotes "The firm will close the plant." exactly, but in the article that sentence was one option the firm later rejected. The summary is verbatim. What went wrong?Analyze
16. An entity-level comparison finds "Acme Corp" in the summary but nowhere in the source. How should the check treat it?Analyze
17. A compliance team will act on your summarizer's output without reading the source document. Why should you default to extractive summarization for this content?Design
18. You are shipping a summarizer and must choose its evaluation reports. Which set matches the lesson's production recommendation?Design
19. You adopt G-Eval as the judge for coherence and factuality in production. What does the lesson say to do before trusting its scores?Design

Use It

Here's the 2026 stack, by use case:

Use caseRecommended
News, 3-5 sentence summary, Englishfacebook/bart-large-cnn
Scientific papersgoogle/pegasus-pubmed or a tuned T5
Multi-document, long-formAny LLM with 32k+ context, prompted
Dialog summarizationphilschmid/bart-large-cnn-samsum
Extractive, low hallucination risk by constructionTextRank or sumy's LSA / LexRank

When compute isn't the constraint, LLMs with long context often beat specialized models outright. What you give up is cost and reproducibility: specialized models are cheaper per call and hold their output steadier across runs.

Check: Use It0/3
1. When compute is not the constraint, long-context LLMs often beat specialized summarizers. What do you give up by choosing them?Explain
2. You must summarize scientific papers, not news. Which starting point does the lesson's stack recommend?Apply
3. You need to summarize chat dialogs between support agents and customers. Which checkpoint does the lesson's stack list for this?Apply

Ship It

Save as outputs/skill-summary-picker.md:

markdown
---
name: summary-picker
description: Pick extractive or abstractive, named library, factuality check.
version: 1.0.0
phase: 5
lesson: 12
tags: [nlp, summarization]
---
 
Given a task (document type, compliance requirement, length, compute budget), output:
 
1. Approach. Extractive or abstractive. Explain in one sentence why.
2. Starting model / library. Name it. `sumy.TextRankSummarizer`, `facebook/bart-large-cnn`, `google/pegasus-pubmed`, or an LLM prompt.
3. Evaluation plan. ROUGE-1, ROUGE-2, ROUGE-L (use rouge-score with stemming). Plus factuality check if abstractive.
4. One failure mode to probe. Entity swap is the most common in abstractive news summarization; flag samples where source entities do not appear in summary.
 
Refuse abstractive summarization for medical, legal, financial, or regulated content without a factuality gate. Flag input over the model's context window as needing chunked map-reduce summarization (not just truncation).
Check: Ship It0/2
1. A 300-page report is far longer than the summarizer's context window. What does the summary-picker spec say to do?Apply
2. A user asks the summary-picker skill to recommend abstractive summarization for legal contracts and mentions there is no factuality check. What does the spec say it must do?Apply
Author's Note

The choice between extractive and abstractive rarely gets made on merit. It gets made on vibes: abstractive demos better, so it's what gets pitched, and extractive gets treated as the fallback for teams that couldn't get the fancy version working. That's backwards for anything where being wrong costs money or trust. I default to extractive first for any document someone will act on without reading the source, and reach for abstractive only once a real factuality check sits in front of it, not bolted on after. ROUGE will not save you here — a summary can score well and still misquote the one sentence that mattered. Read the failure-mode list above twice before you point anything abstractive at a compliance-adjacent surface.

Exercises

  1. Easy. Run TextRank on 5 news articles. Compare the top-3 sentences to a reference summary. Measure ROUGE-L. You should see 30-45 ROUGE-L on CNN/DailyMail-style articles.
  2. Medium. Implement entity-level factuality: extract named entities from source and summary (spaCy), compute recall of source entities in summary and precision of summary entities against source. High precision and low recall mean safe but terse; low precision means hallucinated entities.
  3. Hard. Compare BART-large-CNN against an LLM (Claude or GPT-4) on 50 CNN/DailyMail articles. Report ROUGE-L, factuality (by entity F1), and cost per summary. Document where each wins.

Key Terms

TermWhat people sayWhat it actually means
ExtractivePick sentencesReturn sentences verbatim from the source. Never hallucinates.
AbstractiveRewriteGenerate new text conditioned on source. Can hallucinate.
ROUGESummary metricN-gram / LCS overlap between system output and reference.
TextRankGraph-based extractivePageRank over sentence similarity graph.
FactualityIs it rightWhether summary claims are supported by the source.
HallucinationMade-up contentContent in the summary that the source does not support.

Further Reading

Code

Ships With