💥 BREAKING CHANGE: All metric scores are now HIGHER THE BETTER. Read changelog →
Others

Summarization

LLM-as-a-judge
Referenceless
Multimodal

The summarization metric uses LLM-as-a-judge to determine whether your LLM (application) is generating factually correct summaries while including the necessary details from the original text. In a summarization task within deepeval, the original text refers to the input while the summary is the actual_output.

Required Arguments

To use the SummarizationMetric, you'll have to provide the following arguments when creating an LLMTestCase:

  • input
  • actual_output

Read the How Is It Calculated section below to learn how test case parameters are used for metric calculation.

Usage

Let's take this input and actual_output as an example:

# This is the original text to be summarized
input = """
The 'coverage score' is calculated as the percentage of assessment questions
for which both the summary and the original document provide a 'yes' answer. This
method ensures that the summary not only includes key information from the original
text but also accurately represents it. A higher coverage score indicates a
more comprehensive and faithful summary, signifying that the summary effectively
encapsulates the crucial points and details from the original content.
"""

# This is the summary, replace this with the actual output from your LLM application
actual_output="""
The coverage score quantifies how well a summary captures and
accurately represents key information from the original text,
with a higher score indicating greater comprehensiveness.
"""

You can use the SummarizationMetric as follows for end-to-end evaluation:

from deepeval.metrics import SummarizationMetric
from deepeval.test_case import LLMTestCase
from deepeval import evaluate
...

test_case = LLMTestCase(input=input, actual_output=actual_output)
metric = SummarizationMetric(
    threshold=0.5,
    model="gpt-4",
    assessment_questions=[
        "Is the coverage score based on a percentage of 'yes' answers?",
        "Does the score ensure the summary's accuracy with the source?",
        "Does a higher score mean a more comprehensive summary?"
    ]
)

# To run metric as a standalone
# metric.measure(test_case)
# print(metric.score, metric.reason)

evaluate(test_cases=[test_case], metrics=[metric])

There are TEN optional parameters when instantiating an SummarizationMetric class:

  • [Optional] threshold: the passing threshold. Can also be set to None to run the metric in score-only mode. Defaulted to 0.5.
  • [Optional] assessment_questions: a list of close-ended questions that can be answered with either a 'yes' or a 'no'. These are questions you want your summary to be able to ideally answer, and is especially helpful if you already know what a good summary for your use case looks like. If assessment_questions is not provided, we will generate a set of assessment_questions for you at evaluation time. The assessment_questions are used to calculate the coverage score.
  • [Optional] n: the number of assessment questions to generate when assessment_questions is not provided. Defaulted to 5.
  • [Optional] model: a string specifying which of OpenAI's GPT models to use, OR any custom LLM model of type DeepEvalBaseLLM. Defaulted to gpt-5.4.
  • [Optional] include_reason: a boolean which when set to True, will include a reason for its evaluation score. Defaulted to True.
  • [Optional] strict_mode: a boolean which when set to True, enforces a strict evaluation criterion. In strict mode, the metric score becomes binary: a score of 1 indicates a perfect result, and any outcome less than perfect is scored as 0. Defaulted as False.
  • [Optional] async_mode: a boolean which when set to True, enables concurrent execution within the measure() method. Defaulted to True.

  • [Optional] verbose_mode: a boolean which when set to True, prints the intermediate steps used to calculate said metric to the console, as outlined in the How Is It Calculated section. Defaulted to False.
  • [Optional] truths_extraction_limit: a number which when set, determines the maximum number of factual truths to extract from the input. The truths extracted will used to determine the alignment score, and will be ordered by importance, decided by your evaluation model. Defaulted to None.
  • [Optional] flaky: a boolean which when set to True, marks the metric as flaky. Defaulted to False.

Within components

You can also run the SummarizationMetric within nested components for component-level evaluation.

from deepeval.dataset import EvaluationDataset, Golden
from deepeval.tracing import observe, update_current_span
...

@observe(metrics=[metric])
def inner_component():
    # Set test case at runtime
    test_case = LLMTestCase(input="...", actual_output="...")
    update_current_span(test_case=test_case)
    return

@observe
def llm_app(input: str):
    # Component can be anything from an LLM call, retrieval, agent, tool use, etc.
    inner_component()
    return

dataset = EvaluationDataset(goldens=[Golden(input="Hi!")])
for golden in dataset.evals_iterator():
    llm_app(golden.input)

As a standalone

You can also run the SummarizationMetric on a single test case as a standalone, one-off execution.

...

metric.measure(test_case)
print(metric.score, metric.reason)

How Is It Calculated?

The SummarizationMetric score is calculated according to the following equation:

Summarization=min(Alignment Score,Coverage Score)\text{Summarization} = \min(\text{Alignment Score}, \text{Coverage Score})

To break it down, the:

  • The alignment score determines whether the summary contains hallucinated or contradictory information to the original text.
  • The coverage score determines whether the summary contains the necessary information from the original text.

While the alignment score is similar to that of the HallucinationMetric, the coverage score is first calculated by generating n closed-ended questions that can only be answered with either a 'yes or a 'no', before calculating the ratio of which the original text and summary yields the same answer. Here is a great article on how deepeval's summarization metric was build.

You can access both scores through a SummarizationMetric's score breakdown as follows:

from deepeval.metrics import SummarizationMetric
from deepeval.test_case import LLMTestCase
...

test_case = LLMTestCase(...)
metric = SummarizationMetric(...)

metric.measure(test_case)
print(metric.score)
print(metric.reason)
print(metric.score_breakdown)

FAQs

My summary is factually accurate, so why is it scored so low?
The score is the lower of the alignment and coverage scores, so an accurate summary that drops key details is capped by a low coverage score. Check metric.score_breakdown to see which half is dragging it down.
How does the metric detect hallucinated vs. omitted information?
Two separate checks. The alignment score flags summary claims that contradict or invent detail (hallucination); the coverage score uses yes/no questions to catch key points left out (omission).
When should I supply assessment questions instead of letting deepeval generate them?
Supply assessment_questions when you know what a good summary must answer — they pin the coverage score to the points you care about. Omitting them auto-generates n questions (default 5), fine for exploration but less deterministic.
How do I keep the metric focused on only the most important facts?
Set truths_extraction_limit to cap how many factual truths are pulled from the input. Truths are ordered by importance, so a limit avoids penalizing long documents over minor details. Defaults to None.

On this page