Introduction

At the time of writing this blog, it seems the most popular topics in software engineering are Artificial Intelligence (AI) and Large Language Models (LLMs). LLMs are being proactively integrated into production systems for various purposes and goals, leading to the critical question: “How can we be certain the model performs well?

Traditional software is deterministic and can be tested with clear pass/fail decisions. On the other hand, LLMs are notorious for being non-deterministic, which is embedded in their very nature. Without getting into details on the underlying architecture or how they perceive the world, LLMs are known for their hallucinations, drifting away from their targeted task, being too agreeable, etc. 

These types of problems force us to adopt a different approach when it comes to grading the quality of our LLM-dependent systems. We shift our perspective to evaluation, i.e., scoring the output by a predefined scale, usually [0,1], instead of the traditional binary pass/fail. Different frameworks try to provide the best solution, and the one that stands out amongst many is DeepEval.

What is DeepEval?

DeepEval is an open-source Python evaluation framework for LLMs. With the main goal being to unit test LLMs, DeepEval operates similarly to Pytest, along with the additional caveats attributed to LLMs. DeepEval supports end-to-end as well as component-level evaluation. 

DeepEval’s approach to evaluation relies on the following components:

  1. Test Case – a single interaction between the user and the LLM. This is a container that includes data for a specific evaluation and consists of:
  • input – the prompt sent to the LLM
  • actual_output – the recorded LLM response
  • expected_output – the gold standard response for comparison (if available)
  1. Metrics – definition of the scoring rule used to evaluate the Test Case. They may be:
  • Deterministic – use fixed algorithms and formulae (ex., exact matches, regex, ROUGE/BLEU, LaBSE…)
  • Non-deterministic (LLM-as-a-Judge) – use an independent powerful model to “read” and assess the output.
  1. Evaluation Dataset – collection of Test Cases grouped together

Individual Test Case Evaluation

Ideal evaluation workflow using DeepEval

Basic evaluation through an example

The problem

We can imagine working on an LLM-based assistant that answers questions from retrieved documents. How do we verify whether the response is faithful to the source and is semantically correct?

Setup

pip install deepeval sentence-transformers
export OPENAI_API_KEY="your-api-key-here"

The OpenAI key is needed for the LLM-as-a-judge metric, while deterministic metrics run without external calls. 

The test case

from deepeval.test_case import LLMTestCase

test_case = LLMTestCase(
input="What is Varnish?",
actual_output="Varnish is an HTTP reverse proxy that caches responses in RAM.",
expected_output="Varnish is a caching HTTP reverse proxy that accelerates web applications.",
retrieval_context=[
"Varnish is a HTTP reverse proxy and a caching server that ",
"speeds up web applications by caching HTTP responses."
]
)

Two metrics will be used for this test case. One is an LLM-as-a-Judge metric, and the other is a deterministic metric that will utilize LaBSE. The sentence-transformers package is used for LaBSE. 

The retrieval_context is text fetched from a knowledge base that the LLM uses as source material when generating its answer. The retrieval_context is needed when we want to test the model against specific issues. (hallucinations, etc.)

Language-agnostic BERT Sentence Embedding (LaBSE) is a multilingual sentence embedding model. It is used to compute the cosine similarity between the actual and expected outputs to evaluate semantic similarity.

Metric 1: Faithfulness (LLM-as-a-Judge)

LLM-as-a-Judge metrics use a secondary independent LLM to evaluate and score the primary model’s output. DeepEval has different built-in options:

from deepeval.metrics import (
AnswerRelevancyMetric, # Does the output answer the question?
FaithfulnessMetric, # Is the output grounded in the retrieval context?
ContextualRelevancyMetric,# Is the retrieved context relevant to the question?
HallucinationMetric, # Does the output contain fabricated claims not in the context?
GEval,
# Custom LLM-judged metric using criteria you define. The criteria is defined via a separate prompt.
)

For our use case, we will use the Faithfulness metric to check if the actual LLM output is grounded in the retrieval context.

from deepeval.metrics import FaithfulnessMetric

faithfulness = FaithfulnessMetric(threshold=0.8)

Because the evaluation itself is performed by an LLM, scores may slightly vary between runs.

Metric 2: LaBSE semantic similarity (deterministic)

from deepeval.metrics import BaseMetric
from deepeval.test_case import LLMTestCase
from sentence_transformers import SentenceTransformer, util


class LaBSESimilarityMetric(BaseMetric):
"""Deterministic semantic similarity using LaBSE embeddings."""

def __init__(self, threshold: float = 0.7):
self.threshold = threshold
self.score = 0
self.success = False
self.model = SentenceTransformer("sentence-transformers/LaBSE")

async def a_measure(self, test_case: LLMTestCase, *args, **kwargs) -> float:
return self.measure(test_case)

def measure(self, test_case: LLMTestCase) -> float:
embeddings = self.model.encode(
[test_case.actual_output, test_case.expected_output],
convert_to_tensor=True,
)
self.score = util.cos_sim(embeddings[0], embeddings[1]).item()
self.success = self.score >= self.threshold
return self.score

def is_successful(self) -> bool:
return self.success

@property
def __name__(self):
return "LaBSE Semantic Similarity"

The class extends BaseMetric from DeepEval and implements:

  • measure — encodes both actual_output and expected_output into embeddings, computes their cosine similarity, and tests it against the threshold.
  • a_measure — async wrapper required by DeepEval’s interface
  • is_successful — returns whether the measurement passed the threshold.

For the same inputs, LaBSE always produces the same embeddings, which follow with the same cosine similarity score. As a result, this metric is fully deterministic and reproducible.

Running both metrics on one test case

from deepeval import assert_test

def test_varnish_response():
assert_test(test_case, [
FaithfulnessMetric(threshold=0.8), # non-deterministic
LaBSESimilarityMetric(threshold=0.7), # deterministic
])

Assuming the file containing the mentioned code is named test_varnish.py, the tests can be invoked through the following command:

deepeval test run test_varnish.py

Running the command produces the output:

The test passes only if both metrics meet their thresholds. The faithfulness check ensures the output doesn’t hallucinate beyond the context, while the LaBSE similarity check ensures it remains semantically close to the expected answer.


Conclusion

LLM-as-a-Judge can be used for free-form text where it is hard (or sometimes impossible) to define the correctness of an answer. (summaries, explanations, faithfulness, etc.) Deterministic metrics should be used for tasks with clearly defined correct outputs and where reproducible scores are needed. Another advantage of deterministic metrics is the avoidance of LLM-judge-related costs. In practice, the most effective evaluation suites combine both approaches.

DeepEval provides a bridge between the familiar world of Pytest and the modern requirements of LLM testing. By combining LLM-judged metrics for subjective quality assessment with deterministic metrics for measurable correctness, it provides a complete evaluation toolkit that can be easily run from the CLI or a CI pipeline.

References:

Feng, F., Yang, Y., Cer, D., Arivazhagan, N., & Wang, W. (2020, July 3). Language-agnostic BERT sentence embedding. arXiv.org. https://arxiv.org/abs/2007.01852

DeepEval by Confident AI. (2026, April 5). Quick Introduction. https://deepeval.com/docs/getting-started

LLM-as-a-Judge Metrics | Confident AI Docs. (n.d.). Confident AI Docs. https://www.confident-ai.com/docs/llm-evaluation/core-concepts/llm-as-a-judge

Ip, J. (2025, October 10). LLM-as-a-Judge simply explained: The complete guide to run LLM evals at scale. Confident AI. https://www.confident-ai.com/blog/why-llm-as-a-judge-is-the-best-llm-evaluation-method

DeepEval by Confident AI. (2026a, April 5). “Do it yourself” Metrics. https://deepeval.com/docs/metrics-custom

Zheng, L., Chiang, W., Sheng, Y., Zhuang, S., Wu, Z., Zhuang, Y., Lin, Z., Li, Z., Li, D., Xing, E. P., Zhang, H., Gonzalez, J. E., & Stoica, I. (2023, June 9). Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena. arXiv.org. https://arxiv.org/abs/2306.05685

Leave a comment

Your email address will not be published. Required fields are marked *