0d3cb498a3
CI / Shell Format Check (push) Has been cancelled
CI / Check Ruby (3.4) (push) Has been cancelled
CI / CI Config (push) Has been cancelled
CI / Test on Node ${{ matrix.node }} and ${{ matrix.os }}${{ matrix.shard && format(' (shard {0}/3)', matrix.shard) || '' }} (push) Has been cancelled
CI / Build on Node ${{ matrix.node }} (push) Has been cancelled
CI / Style Check (push) Has been cancelled
CI / Generate Assets (push) Has been cancelled
CI / Check Python (3.14) (push) Has been cancelled
CI / Check Python (3.9) (push) Has been cancelled
CI / Build Docs (push) Has been cancelled
CI / Code Scan Action (push) Has been cancelled
CI / Site tests (push) Has been cancelled
CI / webui tests (push) Has been cancelled
CI / Run Integration Tests (push) Has been cancelled
CI / Run Smoke Tests (push) Has been cancelled
CI / Go Tests (push) Has been cancelled
CI / Share Test (push) Has been cancelled
CI / Redteam (Production API) (push) Has been cancelled
CI / Redteam (Staging API) (push) Has been cancelled
CI / GitHub Actions Lint (push) Has been cancelled
CI / Check Ruby (3.0) (push) Has been cancelled
release-please / release-please (push) Has been cancelled
release-please / build (push) Has been cancelled
release-please / publish-npm (push) Has been cancelled
release-please / publish-npm-backfill (push) Has been cancelled
release-please / docker (push) Has been cancelled
release-please / publish-code-scan-action (push) Has been cancelled
release-please / attest-code-scan-action (push) Has been cancelled
Deploy local.promptfoo.app / Deploy to Cloudflare Pages (push) Has been cancelled
Test and Publish Multi-arch Docker Image / test (push) Has been cancelled
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-amd64 platform:linux/amd64 runner:ubuntu-latest]) (push) Has been cancelled
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-arm64 platform:linux/arm64 runner:ubuntu-24.04-arm]) (push) Has been cancelled
Test and Publish Multi-arch Docker Image / merge-docker-digests (push) Has been cancelled
Test and Publish Multi-arch Docker Image / Attest Multi-arch Image (push) Has been cancelled
Validate Renovate Config / Validate Renovate Configuration (push) Has been cancelled
329 lines
13 KiB
Markdown
329 lines
13 KiB
Markdown
---
|
|
sidebar_position: 1
|
|
title: Evaluating Factuality
|
|
description: How to evaluate the factual accuracy of LLM outputs against reference information using promptfoo's factuality assertion
|
|
---
|
|
|
|
# Evaluating factuality
|
|
|
|
## What is factuality and why is it important?
|
|
|
|
Factuality is the measure of how accurately an LLM's response aligns with established facts or reference information. Simply put, it answers the question: "Is what the AI saying actually true?"
|
|
|
|
**A concrete example:**
|
|
|
|
> **Question:** "What is the capital of France?"
|
|
> **AI response:** "The capital of France is Paris, which has been the country's capital since 987 CE."
|
|
> **Reference fact:** "Paris is the capital of France."
|
|
>
|
|
> In this case, the AI response is factually accurate (it includes the correct capital) but adds additional information about when Paris became the capital.
|
|
|
|
As LLMs become increasingly integrated into critical applications, ensuring they provide factually accurate information is essential for:
|
|
|
|
- **Building trust**: Users need confidence that AI responses are reliable and truthful. _For example, a financial advisor chatbot that gives incorrect information about tax laws could cause users to make costly mistakes and lose trust in your service._
|
|
|
|
- **Reducing misinformation**: Factually incorrect AI outputs can spread misinformation at scale. _For instance, a healthcare bot incorrectly stating that a common vaccine is dangerous could influence thousands of patients to avoid important preventative care._
|
|
|
|
- **Supporting critical use cases**: Applications in healthcare, finance, education, and legal domains require high factual accuracy. _A legal assistant that misrepresents case law precedents could lead to flawed legal strategies with serious consequences._
|
|
|
|
- **Improving model selection**: Comparing factuality across models helps choose the right model for your application. _A company might discover that while one model is more creative, another has 30% better factual accuracy for technical documentation._
|
|
|
|
- **Identifying hallucinations**: Factuality evaluation helps detect when models "make up" information. _For example, discovering that your product support chatbot fabricates non-existent troubleshooting steps 15% of the time would be a critical finding._
|
|
|
|
promptfoo's factuality evaluation enables you to systematically measure how well your model outputs align with reference facts, helping you identify and address issues before they reach users.
|
|
|
|
## Quick Start: Try it today
|
|
|
|
The fastest way to get started with factuality evaluation is to use our pre-built TruthfulQA example:
|
|
|
|
```bash
|
|
# Initialize the example - this command creates a new directory with all necessary files
|
|
npx promptfoo@latest init --example huggingface/dataset-factuality
|
|
|
|
# Change into the newly created directory
|
|
cd huggingface/dataset-factuality
|
|
|
|
# Run the evaluation - this executes the factuality tests using the models specified in the config
|
|
npx promptfoo eval
|
|
|
|
# View the results in an interactive web interface
|
|
npx promptfoo view
|
|
```
|
|
|
|
What these commands do:
|
|
|
|
1. The first command initializes a new project using our huggingface/dataset-factuality example template
|
|
2. The second command navigates into the project directory
|
|
3. The third command runs the factuality evaluation against the TruthfulQA dataset
|
|
4. The final command opens the results in your browser for analysis
|
|
|
|
This example:
|
|
|
|
- Fetches the TruthfulQA dataset (designed to test model truthfulness)
|
|
- Creates test cases with built-in factuality assertions
|
|
- Compares model outputs against reference answers
|
|
- Provides detailed factuality scores and analysis
|
|
|
|
You can easily customize it by:
|
|
|
|
- Uncommenting additional providers in `promptfooconfig.yaml` to test more models
|
|
- Adjusting the prompt template to change how questions are asked
|
|
- Modifying the factuality scoring weights to match your requirements
|
|
|
|
## How factuality evaluation works
|
|
|
|
promptfoo implements a structured factuality evaluation methodology based on [OpenAI's evals](https://github.com/openai/evals/blob/main/evals/registry/modelgraded/fact.yaml), using the [`factuality`](/docs/configuration/expected-outputs#model-assisted-eval-metrics) assertion type.
|
|
|
|
The model-graded factuality check takes the following three inputs:
|
|
|
|
- **Prompt**: prompt sent to the LLM
|
|
- **Output**: text produced by the LLM
|
|
- **Reference**: the ideal LLM output, provided by the author of the eval
|
|
|
|
### Key terminology explained
|
|
|
|
The evaluation classifies the relationship between the LLM output and the reference into one of five categories:
|
|
|
|
- **A**: Output is a subset of the reference and is fully consistent with it
|
|
- _Example: If the reference is "Paris is the capital of France and has a population of 2.1 million," a subset would be "Paris is the capital of France" — it contains less information but is fully consistent_
|
|
|
|
- **B**: Output is a superset of the reference and is fully consistent with it
|
|
- _Example: If the reference is "Paris is the capital of France," a superset would be "Paris is the capital of France and home to the Eiffel Tower" — it adds accurate information while maintaining consistency_
|
|
|
|
- **C**: Output contains all the same details as the reference
|
|
- _Example: If the reference is "The Earth orbits the Sun," and the output is "The Sun is orbited by the Earth" — same information, different wording_
|
|
|
|
- **D**: Output and reference disagree
|
|
- _Example: If the reference is "Paris is the capital of France," but the output claims "Lyon is the capital of France" — this is a factual disagreement_
|
|
|
|
- **E**: Output and reference differ, but differences don't affect factuality
|
|
- _Example: If the reference is "The distance from Earth to the Moon is 384,400 km," and the output says "The Moon is about 384,000 km from Earth" — the small difference doesn't materially affect factuality_
|
|
|
|
By default, categories A, B, C, and E are considered passing (with customizable scores), while category D (disagreement) is considered failing.
|
|
|
|
## Creating a basic factuality evaluation
|
|
|
|
To set up a simple factuality evaluation for your LLM outputs:
|
|
|
|
1. **Create a configuration file** with a factuality assertion:
|
|
|
|
```yaml title="promptfooconfig.yaml"
|
|
providers:
|
|
- openai:gpt-5-mini
|
|
prompts:
|
|
- |
|
|
Please answer the following question accurately:
|
|
Question: What is the capital of {{location}}?
|
|
tests:
|
|
- vars:
|
|
location: California
|
|
assert:
|
|
- type: factuality
|
|
value: The capital of California is Sacramento
|
|
```
|
|
|
|
2. **Run your evaluation**:
|
|
|
|
```bash
|
|
npx promptfoo eval
|
|
npx promptfoo view
|
|
```
|
|
|
|
This will produce a report showing how factually accurate your model's responses are compared to the reference answers.
|
|
|
|
## Comparing Multiple Models
|
|
|
|
Factuality evaluation is especially useful for comparing how different models perform on the same facts:
|
|
|
|
```yaml title="promptfooconfig.yaml"
|
|
providers:
|
|
- openai:gpt-5-mini
|
|
- openai:gpt-5
|
|
- anthropic:claude-sonnet-4-6
|
|
- google:gemini-2.0-flash
|
|
prompts:
|
|
- |
|
|
Question: What is the capital of {{location}}?
|
|
Please answer accurately.
|
|
tests:
|
|
- vars:
|
|
location: California
|
|
assert:
|
|
- type: factuality
|
|
value: The capital of California is Sacramento
|
|
- vars:
|
|
location: New York
|
|
assert:
|
|
- type: factuality
|
|
value: Albany is the capital of New York
|
|
```
|
|
|
|
## Evaluating On External Datasets
|
|
|
|
For comprehensive evaluation, you can run factuality tests against external datasets like TruthfulQA, which we covered in the Quick Start section.
|
|
|
|
### Creating Your Own Dataset Integration
|
|
|
|
You can integrate any dataset by:
|
|
|
|
1. **Create a dataset loader**: Use JavaScript/TypeScript to fetch and format your dataset
|
|
2. **Add factuality assertions**: Include a factuality assertion in each test case
|
|
3. **Reference in your config**:
|
|
|
|
```yaml
|
|
tests: file://your_dataset_loader.ts:generate_tests
|
|
```
|
|
|
|
## Crafting Effective Reference Answers
|
|
|
|
The quality of your reference answers is crucial for accurate factuality evaluation. Here are specific guidelines:
|
|
|
|
### What makes a good reference answer?
|
|
|
|
1. **Clarity**: State the fact directly and unambiguously
|
|
- _Good: "The capital of France is Paris."_
|
|
- _Avoid: "As everyone knows, the beautiful city of Paris serves as the capital of the magnificent country of France."_
|
|
|
|
2. **Precision**: Include necessary details without extraneous information
|
|
- _Good: "Water freezes at 0 degrees Celsius at standard atmospheric pressure."_
|
|
- _Avoid: "Water, H2O, freezes at 0 degrees Celsius, which is also 32 degrees Fahrenheit, creating ice that floats."_
|
|
|
|
3. **Verifiability**: Ensure your reference is backed by authoritative sources
|
|
- _Good: "According to the World Health Organization, the COVID-19 pandemic was declared on March 11, 2020."_
|
|
- _Avoid: "The COVID pandemic started sometime in early 2020."_
|
|
|
|
4. **Completeness**: Include all essential parts of the answer
|
|
- _Good: "The three branches of the U.S. federal government are executive, legislative, and judicial."_
|
|
- _Avoid: "The U.S. government has three branches."_
|
|
|
|
### Common pitfalls to avoid
|
|
|
|
1. **Subjective statements**: Avoid opinions or judgments in reference answers
|
|
2. **Temporally dependent facts**: Be careful with time-sensitive information
|
|
3. **Ambiguous wording**: Ensure there's only one way to interpret the statement
|
|
4. **Unnecessary complexity**: Keep references simple enough for clear evaluation
|
|
|
|
## Customizing the Evaluation
|
|
|
|
### Selecting the Grading Provider
|
|
|
|
By default, promptfoo uses `gpt-5` for grading. To specify a different grading model:
|
|
|
|
```yaml
|
|
defaultTest:
|
|
options:
|
|
# Set the provider for grading factuality
|
|
provider: openai:gpt-5
|
|
```
|
|
|
|
You can also override it per assertion:
|
|
|
|
```yaml
|
|
assert:
|
|
- type: factuality
|
|
value: The capital of California is Sacramento
|
|
provider: anthropic:claude-sonnet-4-6
|
|
```
|
|
|
|
Or via the command line:
|
|
|
|
```bash
|
|
promptfoo eval --grader openai:gpt-5
|
|
```
|
|
|
|
### Customizing Scoring Weights
|
|
|
|
Tailor the factuality scoring to your specific requirements:
|
|
|
|
```yaml
|
|
defaultTest:
|
|
options:
|
|
factuality:
|
|
subset: 1.0 # Category A: Output is a subset of reference
|
|
superset: 0.8 # Category B: Output is a superset of reference
|
|
agree: 1.0 # Category C: Output contains all the same details
|
|
disagree: 0.0 # Category D: Output and reference disagree
|
|
differButFactual: 0.7 # Category E: Differences don't affect factuality
|
|
```
|
|
|
|
#### Understanding the default scoring weights
|
|
|
|
By default, promptfoo uses a simple binary scoring system:
|
|
|
|
- Categories A, B, C, and E are assigned a score of 1.0 (pass)
|
|
- Category D (disagree) is assigned a score of 0.0 (fail)
|
|
|
|
**When to use custom weights:**
|
|
|
|
- Decrease `superset` if you're concerned about models adding potentially incorrect information
|
|
- Reduce `differButFactual` if precision in wording is important for your application
|
|
- Adjust `subset` downward if comprehensive answers are required
|
|
|
|
A score of 0 means fail, while any positive score is considered passing. The score values can be used for ranking and comparing model outputs.
|
|
|
|
### Customizing the Evaluation Prompt
|
|
|
|
For complete control over how factuality is evaluated, customize the prompt:
|
|
|
|
```yaml
|
|
defaultTest:
|
|
options:
|
|
rubricPrompt: |
|
|
You are an expert factuality evaluator. Compare these two answers:
|
|
|
|
Question: {{input}}
|
|
Reference answer: {{ideal}}
|
|
Submitted answer: {{completion}}
|
|
|
|
Determine if the submitted answer is factually consistent with the reference answer.
|
|
Choose one option:
|
|
A: Submitted answer is a subset of reference (fully consistent)
|
|
B: Submitted answer is a superset of reference (fully consistent)
|
|
C: Submitted answer contains same details as reference
|
|
D: Submitted answer disagrees with reference
|
|
E: Answers differ but differences don't affect factuality
|
|
|
|
Respond with JSON: {"category": "LETTER", "reason": "explanation"}
|
|
```
|
|
|
|
You must implement the following template variables:
|
|
|
|
- `{{input}}`: The original prompt/question
|
|
- `{{ideal}}`: The reference answer (from the `value` field)
|
|
- `{{completion}}`: The LLM's actual response (provided automatically by promptfoo)
|
|
|
|
## Response Formats
|
|
|
|
The factuality checker supports two response formats:
|
|
|
|
1. **JSON format** (primary and recommended):
|
|
|
|
```json
|
|
{
|
|
"category": "A",
|
|
"reason": "The submitted answer is a subset of the expert answer and is fully consistent with it."
|
|
}
|
|
```
|
|
|
|
2. **Single Letter** (legacy format):
|
|
|
|
```
|
|
(A) The submitted answer is a subset of the expert answer and is fully consistent with it.
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
When setting up factuality evaluations:
|
|
|
|
1. **Choose reference answers carefully**: They should be accurate, clear, and comprehensive
|
|
2. **Consider multiple providers**: Different models may excel at different types of factual knowledge
|
|
3. **Customize scoring weights**: Adjust based on your application's tolerance for different types of factual issues
|
|
4. **Use a strong grader**: More capable models generally provide more reliable factuality assessments
|
|
5. **Test with known examples**: Validate your setup with questions where you know the correct answers
|
|
|
|
## See Also
|
|
|
|
- [Model-graded metrics](/docs/configuration/expected-outputs/model-graded) for more evaluation options
|
|
- [Factuality assertion reference](/docs/configuration/expected-outputs/model-graded/factuality)
|
|
- [TruthfulQA example on GitHub](https://github.com/promptfoo/promptfoo/tree/main/examples/huggingface/dataset-factuality) - Complete code for the TruthfulQA factuality evaluation example
|