Cheat sheets

Summarization, QA, NLI and Multilingual NLP

Summarize, answer, check entailment and transfer across languages. Models, metrics, defaults and failures.

  • Concepts and terms
  • Tasks and commands
  • Annotated code
  • Diagrams
  • Defaults and numbers
  • Troubleshooting
  • Questions and tips

Source

Grounded QA with an NLI gate#

searchpassagesanswerentailmentclientQuestionprocessRetrievertop-k passagesmodelReaderspan or LLM answermodelNLI checkcontext entailsanswer?storeCorpusBM25, dense orhybridclientAnsweror "I don't know"searchpassagesanswerentailmentclientQuestionprocessRetrievertop-k passagesmodelReaderspan or LLM answermodelNLI checkcontext entailsanswer?storeCorpusBM25, dense orhybridclientAnsweror "I don't know"

From Lesson 05.13, Lesson 05.21

Tasks in code#

TaskCode
Extractive summarytextrank(text, top_k=3, damping=0.85, iterations=50, epsilon=1e-4)
Abstractive summarypipeline("summarization", model="facebook/bart-large-cnn")
Generate the summarysummarizer(article, max_length=120, min_length=60, do_sample=False)
ROUGE with stemmingrouge_scorer.RougeScorer(["rouge1", "rouge2", "rougeL"], use_stemmer=True)
Extractive QApipeline("question-answering", model="deepset/roberta-base-squad2")
Allow an empty answerpass handle_impossible_answer=True to the pipeline call
SQuAD metricsexact_match(pred, gold) and token_f1(pred, gold)
Zero-shot topic labelszs(text, candidate_labels=labels)

From Lesson 05.12, Lesson 05.13, 05.13 code/main.py, Lesson 05.21

SQuAD normalization#

def normalize(text):
text = text.lower()
text = re.sub(r"\b(a|an|the)\b", " ", text)remove articles
text = re.sub(r"[^\w\s]", " ", text)remove punctuation
return " ".join(text.split())
exact_match("June 29th, 2007", "June 29, 2007")0.0
token_f1("June 29th, 2007", "June 29, 2007")0.67
token_f1("29 June 2007", "June 29, 2007")1.00, EM is 0
refusal_from_score(top_retrieval_score, threshold=0.3)True means refuse

From 05.13 code/main.py

TextRank, step by step#

1Splitsentence_split cuts after ., ! or ?. Fewsentences: return all.2Graphsimilarity is word overlap over the log of bothlengths.3Iterateeach score is 1 - damping plus damped neighbourscores.4Stopchange below epsilon, or iterations passes.5Outputtop top_k sentences, in document order.

From 05.12 code/main.py, Lesson 05.12

Metrics#

ROUGE-1, ROUGE-2
unigram and bigram overlap with the reference.
ROUGE-L
longest common subsequence. 40 is good. 50 is exceptional.
EM
exact match after normalization. Else the score is 0.
Token F1
F_1 = \frac{2PR}{P + R} over token overlap. It gives partial credit.
BERTScore
contextual embedding similarity. Report it next to ROUGE.
G-Eval
LLM judge with chain-of-thought. Matches humans ~80% of the time.
Entity-level F1
entities that occur only in the summary are suspect.
RAGAS
faithfulness, answer relevance, context precision, context recall.

From Lesson 05.12, Lesson 05.13, 05.13 code/main.py

Questions#

Extractive or abstractive?
Extractive for news, medical, legal and financial text. Abstractive needs a factuality check.
How does zero-shot classification work?
Each label becomes a hypothesis. Pick the label with the highest entailment.
Which source language for transfer?
Try a close high-resource relative first. Hindi for Indic targets.
Why per-language accuracy?
The aggregate hides the long tail.
Does RAGAS need gold answers?
No. It scores four dimensions without references.

From Lesson 05.12, Lesson 05.13, Lesson 05.18, Lesson 05.21

Tips#

  • Always use stemming in ROUGE. Else "running" and "run" do not match.
  • Report ROUGE-L, BERTScore and G-Eval. Calibrate on 50-100 human-labeled summaries.
  • Tell the model to use only the context and to say "I don't know."
  • Always check the score field of the QA pipeline.
  • Run a 100-example labeled sanity check before you ship zero-shot classification.
  • For input over the context window, use chunked map-reduce, not truncation.

From Lesson 05.12, Lesson 05.13, Lesson 05.21

NLI and faithfulness#

nli = pipeline("text-classification",
model="facebook/bart-large-mnli",
top_k=None)return all three labels
result = nli({"text": premise, "text_pair": hypothesis})[0]
zs = pipeline("zero-shot-classification", model="facebook/bart-large-mnli")
result = zs(text, candidate_labels=labels)labels sorted by score
def is_faithful(answer, context, threshold=0.5):
result = nli({"text": context, "text_pair": answer})[0]
entail = next(s for s in result if s["label"] == "entailment")
return entail["score"] > thresholdcontext supports the claim

From Lesson 05.21

Troubleshooting#

SymptomCauseFix
Summary says "John Brown"Entity swap in abstractive outputFlag entities not in the source
"25,000" becomes "25 million"Number driftUse extractive or a factuality gate
Span returned for an unanswerable questionNull score ignored by defaultSet handle_impossible_answer=True
Reader looks badRetriever missed the passageMeasure retrieval recall in top-k
~60% from the hypothesis alone"not", "never" leak the labelHypothesis-only baseline, ANLI
20+ F1 drop on long premisesSentence-level NLI modelUse a DocNLI-trained model
Zero-shot swings 10+ pointsTemplate sensitivityTune hypothesis_template
Hindi output subtly wrong3-5x tokens per wordCheck fertility, byte_fallback=True

From Lesson 05.12, Lesson 05.13, Lesson 05.18, Lesson 05.21

Defaults and numbers#

SettingDefaultNote
TextRank damping0.85PageRank default
TextRank iterations50Stops early below epsilon 1e-4
BART max_length120With min_length=60
Refusal threshold0.3Top retrieval score below it: refuse
is_faithful threshold0.5Entailment score must be above it
Few-shot examples100-500Target language. 95-98% of English
learning_rate2e-5Higher rates collapse the alignment
num_train_epochs5Safe for 100-500 examples

From Lesson 05.12, 05.13 code/main.py, Lesson 05.18, Lesson 05.21

Abbreviations#

ROUGE
Recall-Oriented Understudy for Gisting Evaluation. N-gram and LCS overlap.
SQuAD
Stanford Question Answering Dataset. EM and F1 metrics.
NLI
Natural Language Inference. Entailment, contradiction or neutral.
RTE
Recognizing Textual Entailment. The older name for NLI.
MultiNLI
433k pairs across 10 genres. The standard NLI training corpus.
ANLI
Adversarial NLI. Humans wrote pairs to break models.
XLM-R
100-language RoBERTa on CommonCrawl. Base 270M, Large 550M.
NLLB
No Language Left Behind. 200 languages, 55 low-resource.

From Lesson 05.12, Lesson 05.13, Lesson 05.18, Lesson 05.21

Pick a model#

CommandWhat it does
facebook/bart-large-cnnNews summary of 3 to 5 sentences, English
google/pegasus-pubmedSummaries of scientific papers
philschmid/bart-large-cnn-samsumDialog summaries
deepset/roberta-base-squad2Answer span from a given passage
facebook/bart-large-mnliLightweight zero-shot classification
cross-encoder/nli-deberta-v3-baseFast NLI for the edge
joeddav/xlm-roberta-large-xnliZero-shot classification in many languages
facebook/nllb-200-distilled-600MTranslation, 200 languages

From Lesson 05.12, Lesson 05.13, Lesson 05.18, Lesson 05.21