1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
28 small wins to finish your pathNext lesson →
DiscreteMetric
DiscreteMetric is a RAGAS class that turns a question you write in plain words into a judged metric, where the judge must answer with one of the values you allow.
Last updated: 29 Sep, 2026 · RAGAS 0.4.3
Some qualities no formula can check: tone, politeness, whether an answer sounds like your brand. A DiscreteMetric puts that question to the judge and keeps its answer inside the list you give.
The DiscreteMetric API
from ragas.metrics import DiscreteMetric
metric = DiscreteMetric(
name="...",
allowed_values=["a", "b"], # the only answers the judge may give
prompt="Question ... {response}", # sample fields go in braces
)
metric.score(response=..., llm=judge).valueThe judge is passed when you score, not when you build the metric.
A tone check for the support bot
tone = DiscreteMetric(
name="support_tone",
allowed_values=["friendly", "blunt"],
prompt="Is this customer support reply friendly or blunt? Answer friendly or blunt.\n\nReply: {response}",
)Project files used on this pageThis lesson builds on a project from earlier lessons. The code below imports this file. Click a file to see its code, or follow the link to the lesson that wrote it. To run the code yourself, keep it in the same folder.
- written in LLM as a judge
View the code here
judge.py
import os
from google import genai
from openai import AsyncOpenAI
from ragas.embeddings import GoogleEmbeddings
from ragas.llms import llm_factory
groq = AsyncOpenAI(
api_key=os.environ.get("JUDGE_GROQ", os.environ["GROQ_API_KEY"]),
base_url="https://api.groq.com/openai/v1",
)
judge = llm_factory("openai/gpt-oss-20b", provider="openai", client=groq)
class OneTextPerCall(GoogleEmbeddings):
"""gemini-embedding-2 turns a list into one embedding, so embed each text on its own."""
def embed_texts(self, texts, **kwargs):
return [self.embed_text(text) for text in texts]
async def aembed_texts(self, texts, **kwargs):
return [await self.aembed_text(text) for text in texts]
embeddings = OneTextPerCall(client=genai.Client(), model="gemini-embedding-2")
Judging the tone of two replies
from judge import judge
from ragas.metrics import DiscreteMetric
tone = DiscreteMetric(
name="support_tone",
allowed_values=["friendly", "blunt"],
prompt="Is this customer support reply friendly or blunt? Answer friendly or blunt.\n\nReply: {response}",
)
for reply in ["Thanks for asking! The PixelPhone 15 is priced at $899.", "$899. Read the website."]:
result = tone.score(response=reply, llm=judge)
print(result.value, "|", reply)Output
friendly | Thanks for asking! The PixelPhone 15 is priced at $899. blunt | $899. Read the website.
What the judge decided
- The thanking reply is marked with one allowed value and the curt one with the other; the output shows which.
- The value is always from
allowed_values. RAGAS gives the judge a response class that only accepts those words, so a free-text answer cannot slip through.
DiscreteMetric vs a decorated function
| DiscreteMetric | @discrete_metric | |
|---|---|---|
| Who decides | The judge, reading your prompt | Your Python code |
| Cost | One judge call per sample | Free |
| Good for | Tone, safety, style | Rules a regex can check |
When to write a DiscreteMetric
- Brand voice or politeness rules that a reviewer would otherwise read by hand.
- Safety checks, such as whether a reply gives medical or legal advice.
Watch out. Ask one thing per metric. A prompt that asks whether a reply is polite, correct and complete gets one value for three questions, and you cannot tell which one failed. Three metrics, one question each.
Related
- Previous: Custom metrics
- Next: Datasets
- Reference: Aspect critic
Try it yourself
- Add a third allowed value,
"rude", and a reply that should earn it. - Write a DiscreteMetric that asks whether a reply promises something the store might not do, with values
safeandrisky.
Slow is fine. Stopping is the only problem.