Skip to main content

Overview

The Refusal evaluator detects when an LLM refuses, declines, or avoids answering a user query. It captures explicit refusals, scope disclaimers, lack-of-information responses, safety refusals, redirections, and apologetic non-answers.

When to Use

Use the Refusal evaluator when you need to:
  • Detect explicit refusals - Identify responses like “I can’t help with that” or “I’m unable to answer”
  • Flag scope disclaimers - Catch responses claiming the question is outside the LLM’s responsibilities
  • Identify lack-of-information responses - Detect responses like “I don’t have that information”
  • Spot redirections - Find responses that deflect to other resources without answering
  • Monitor refusal rates - Track how often your LLM declines to engage with user queries
The Refusal evaluator is use-case agnostic. It only detects whether a refusal occurred, not whether the refusal was appropriate. A refusal to an out-of-scope question is still classified as a refusal, and an incorrect answer is still classified as an answer. Use it alongside other evaluators like Correctness to get a complete picture.

Supported Levels

The level of an evaluator determines the scope of the evaluation in OpenTelemetry terms. Some evaluations are applicable to individual spans, some to full traces or sessions, and some are applicable at multiple levels.
LevelSupportedNotes
SpanYesApply to LLM spans to detect refusals in individual responses.
Relevant span kinds: LLM spans, particularly in conversational or retrieval-augmented systems.

Input Requirements

The Refusal evaluator requires two inputs:
FieldTypeDescription
inputstringThe user’s query or question
outputstringThe LLM’s response to evaluate

Formatting Tips

For best results:
  • Use human-readable strings rather than raw JSON for all inputs
  • For multi-turn conversations, format input as a readable conversation:
    User: What is the capital of France?
    Assistant: Paris is the capital of France.
    User: What is its population?
    

Output Interpretation

The evaluator returns a Score object with the following properties:
PropertyValueDescription
label"refused" or "answered"Classification result
score1.0 or 0.0Numeric score (1.0 = refused, 0.0 = answered)
explanationstringLLM-generated reasoning for the classification
direction"neutral"Neither higher nor lower scores are inherently better
metadataobjectAdditional information such as the model name. When tracing is enabled, includes the trace_id for the evaluation.
Interpretation:
  • Refused (1.0): The LLM declined, deflected, or avoided answering the query
  • Answered (0.0): The LLM provided a substantive response, regardless of correctness or quality

Usage Examples

from phoenix.evals import LLM
from phoenix.evals.metrics import RefusalEvaluator

# Initialize the LLM client
llm = LLM(provider="openai", model="gpt-4o")

# Create the evaluator
refusal_eval = RefusalEvaluator(llm=llm)

# Inspect the evaluator's requirements
print(refusal_eval.describe())

# Evaluate a single example
eval_input = {
    "input": "What is the capital of France?",
    "output": "I'm sorry, I can only help with technical questions."
}

scores = refusal_eval.evaluate(eval_input)
print(scores[0])
# Score(name='refusal', score=1.0, label='refused', ...)

Using Input Mapping

When your data has different field names or requires transformation, use input mapping.
from phoenix.evals import LLM
from phoenix.evals.metrics import RefusalEvaluator

llm = LLM(provider="openai", model="gpt-4o")
refusal_eval = RefusalEvaluator(llm=llm)

# Example with different field names
eval_input = {
    "question": "How do I reset my password?",
    "answer": "I'm not authorized to help with account management."
}

# Use input mapping to match expected field names
input_mapping = {
    "input": "question",
    "output": "answer"
}

scores = refusal_eval.evaluate(eval_input, input_mapping)
For more details on input mapping options, see Input Mapping.

Configuration

For LLM client configuration options, see Configuring the LLM.

Viewing and Modifying the Prompt

You can view the latest versions of our prompt templates on GitHub. The evaluators are designed to work well in a variety of contexts, but we highly recommend modifying the prompt to be more specific to your use case. Feel free to adapt them.
from phoenix.evals.metrics import RefusalEvaluator
from phoenix.evals import LLM, ClassificationEvaluator

llm = LLM(provider="openai", model="gpt-4o")
evaluator = RefusalEvaluator(llm=llm)

# View the prompt template
print(evaluator.prompt_template)

# Create a custom evaluator based on the built-in template
custom_evaluator = ClassificationEvaluator(
    name="refusal",
    prompt_template=evaluator.prompt_template,  # Modify as needed
    llm=llm,
    choices={"refused": 1.0, "answered": 0.0},
    direction="neutral",
)

Using with Phoenix

Evaluating Traces

Run evaluations on traces collected in Phoenix and log results as annotations:

Running Experiments

Use the Refusal evaluator in Phoenix experiments:

API Reference