autoevals 0.3.0


pip install autoevals

  Latest version

Released: Jun 09, 2026


Meta
Author: BrainTrust
Requires Python: >=3.10.0

Classifiers

Programming Language
  • Python :: 3
  • Python :: 3.10

Operating System
  • OS Independent

Autoevals

Autoevals is a tool to quickly and easily evaluate AI model outputs.

It bundles together a variety of automatic evaluation methods including:

  • LLM-as-a-judge
  • Heuristic (e.g. Levenshtein distance)
  • Statistical (e.g. BLEU)

Autoevals is developed by the team at Braintrust.

Autoevals uses model-graded evaluation for a variety of subjective tasks including fact checking, safety, and more. Many of these evaluations are adapted from OpenAI's excellent evals project but are implemented so you can flexibly run them on individual examples, tweak the prompts, and debug their outputs.

You can also create your own model-graded evaluations with Autoevals. It's easy to add custom prompts, parse outputs, and manage exceptions.

Requirements

  • Python 3.9 or higher
  • Compatible with both OpenAI Python SDK v0.x and v1.x

Installation

TypeScript

npm install autoevals

Python

pip install autoevals

Getting started

Use Autoevals to model-grade an example LLM completion using the Factuality prompt. By default, Autoevals uses your OPENAI_API_KEY environment variable to authenticate with OpenAI's API.

Python

from autoevals.llm import *
import asyncio

# Create a new LLM-based evaluator
evaluator = Factuality()

# Synchronous evaluation
input = "Which country has the highest population?"
output = "People's Republic of China"
expected = "China"

# Using the synchronous API
result = evaluator(output, expected, input=input)
print(f"Factuality score (sync): {result.score}")
print(f"Factuality metadata (sync): {result.metadata['rationale']}")

# Using the asynchronous API
async def main():
    result = await evaluator.eval_async(output, expected, input=input)
    print(f"Factuality score (async): {result.score}")
    print(f"Factuality metadata (async): {result.metadata['rationale']}")

# Run the async example
asyncio.run(main())

TypeScript

import { Factuality } from "autoevals";

(async () => {
  const input = "Which country has the highest population?";
  const output = "People's Republic of China";
  const expected = "China";

  const result = await Factuality({ output, expected, input });
  console.log(`Factuality score: ${result.score}`);
  console.log(`Factuality metadata: ${result.metadata?.rationale}`);
})();

Using other AI providers

When you use Autoevals, it will look for an OPENAI_BASE_URL environment variable to use as the base for requests to an OpenAI-compatible API. If OPENAI_BASE_URL is not set, it will look for a BRAINTRUST_AI_GATEWAY_URL environment variable and then default to the Braintrust Gateway.

When you use the Braintrust Gateway, you'll also get:

  • Simplified access to many AI providers
  • Reduced costs with automatic request caching
  • Increased observability when you enable logging to Braintrust

The Braintrust-hosted Gateway is free to use while it is in beta.

Set the BRAINTRUST_API_KEY environment variable to authenticate Gateway requests. You can also route requests to supported AI providers and models or custom models you have configured in Braintrust.

Python

# NOTE: ensure BRAINTRUST_API_KEY is set in your environment
from autoevals.llm import *

# Create an LLM-based evaluator using the Claude 3.5 Sonnet model from Anthropic
evaluator = Factuality(model="claude-3-5-sonnet-latest")

# Evaluate an example LLM completion
input = "Which country has the highest population?"
output = "People's Republic of China"
expected = "China"

result = evaluator(output, expected, input=input)

# The evaluator returns a score from [0,1] and includes the raw outputs from the evaluator
print(f"Factuality score: {result.score}")
print(f"Factuality metadata: {result.metadata['rationale']}")

TypeScript

// NOTE: ensure BRAINTRUST_API_KEY is set in your environment
import { Factuality } from "autoevals";

(async () => {
  const input = "Which country has the highest population?";
  const output = "People's Republic of China";
  const expected = "China";

  // Run an LLM-based evaluator using the Claude 3.5 Sonnet model from Anthropic
  const result = await Factuality({
    model: "claude-3-5-sonnet-latest",
    output,
    expected,
    input,
  });

  // The evaluator returns a score from [0,1] and includes the raw outputs from the evaluator
  console.log(`Factuality score: ${result.score}`);
  console.log(`Factuality metadata: ${result.metadata?.rationale}`);
})();

Custom client configuration

There are two ways you can configure a custom client when you need to use a different OpenAI compatible API:

  1. Global configuration: Initialize a client that will be used by all evaluators
  2. Instance configuration: Configure a client for a specific evaluator

Global configuration

Set up a client that all your evaluators will use:

Python

import openai
import asyncio
from autoevals import init
from autoevals.llm import Factuality

client = init(openai.AsyncOpenAI(base_url="https://api.openai.com/v1/"))

async def main():
    evaluator = Factuality()
    result = await evaluator.eval_async(
        input="What is the speed of light in a vacuum?",
        output="The speed of light in a vacuum is 299,792,458 meters per second.",
        expected="The speed of light in a vacuum is approximately 300,000 kilometers per second."
    )
    print(f"Factuality score: {result.score}")

asyncio.run(main())

TypeScript

import OpenAI from "openai";
import { init, Factuality } from "autoevals";

const client = new OpenAI({
  baseURL: "https://api.openai.com/v1/",
});

init({ client });

(async () => {
  const result = await Factuality({
    input: "What is the speed of light in a vacuum?",
    output: "The speed of light in a vacuum is 299,792,458 meters per second.",
    expected:
      "The speed of light in a vacuum is approximately 300,000 kilometers per second (or precisely 299,792,458 meters per second).",
  });

  console.log("Factuality Score:", result);
})();

Instance configuration

Configure a client for a specific evaluator instance:

Python

import openai
from autoevals.llm import Factuality

custom_client = openai.OpenAI(base_url="https://custom-api.example.com/v1/")
evaluator = Factuality(client=custom_client)

TypeScript

import OpenAI from "openai";
import { Factuality } from "autoevals";

(async () => {
  const customClient = new OpenAI({
    baseURL: "https://custom-api.example.com/v1/",
  });

  const result = await Factuality({
    client: customClient,
    output: "Paris is the capital of France",
    expected:
      "Paris is the capital of France and has a population of over 2 million",
    input: "Tell me about Paris",
  });
  console.log(result);
})();

Using Braintrust with Autoevals (optional)

Once you grade an output using Autoevals, you can optionally use Braintrust to log and compare your evaluation results. This integration is completely optional and not required for using Autoevals.

TypeScript

Create a file named example.eval.js (it must take the form *.eval.[ts|tsx|js|jsx]):

import { Eval } from "braintrust";
import { Factuality } from "autoevals";

Eval("Autoevals", {
  data: () => [
    {
      input: "Which country has the highest population?",
      expected: "China",
    },
  ],
  task: () => "People's Republic of China",
  scores: [Factuality],
});

Then, run

npx braintrust run example.eval.js

Python

Create a file named eval_example.py (it must take the form eval_*.py):

import braintrust
from autoevals.llm import Factuality

Eval(
    "Autoevals",
    data=lambda: [
        dict(
            input="Which country has the highest population?",
            expected="China",
        ),
    ],
    task=lambda *args: "People's Republic of China",
    scores=[Factuality],
)

Supported evaluation methods

LLM-as-a-judge evaluations

  • Battle
  • Closed QA
  • Humor
  • Factuality
  • Moderation
  • Security
  • Summarization
  • SQL
  • Translation
  • Fine-tuned binary classifiers

RAG evaluations

  • Context precision
  • Context relevancy
  • Context recall
  • Context entity recall
  • Faithfulness
  • Answer relevancy
  • Answer similarity
  • Answer correctness

Composite evaluations

  • Semantic list contains
  • JSON validity

Embedding evaluations

  • Embedding similarity

Heuristic evaluations

  • Levenshtein distance
  • Exact match
  • Numeric difference
  • JSON diff

For detailed documentation on all scorers, including parameters, score ranges, and usage examples, see the Scorer Reference.

Custom evaluation prompts

Autoevals supports custom evaluation prompts for model-graded evaluation. To use them, simply pass in a prompt and scoring mechanism:

Python

from autoevals import LLMClassifier

# Define a prompt prefix for a LLMClassifier (returns just one answer)
prompt_prefix = """
You are a technical project manager who helps software engineers generate better titles for their GitHub issues.
You will look at the issue description, and pick which of two titles better describes it.

I'm going to provide you with the issue description, and two possible titles.

Issue Description: {{input}}

1: {{output}}
2: {{expected}}
"""

# Define the scoring mechanism
# 1 if the generated answer is better than the expected answer
# 0 otherwise
output_scores = {"1": 1, "2": 0}

evaluator = LLMClassifier(
    name="TitleQuality",
    prompt_template=prompt_prefix,
    choice_scores=output_scores,
    use_cot=True,
)

# Evaluate an example LLM completion
page_content = """
As suggested by Nicolo, we should standardize the error responses coming from GoTrue, postgres, and realtime (and any other/future APIs) so that it's better DX when writing a client,
We can make this change on the servers themselves, but since postgrest and gotrue are fully/partially external may be harder to change, it might be an option to transform the errors within the client libraries/supabase-js, could be messy?
Nicolo also dropped this as a reference: http://spec.openapis.org/oas/v3.0.3#openapi-specification"""
output = "Standardize error responses from GoTrue, Postgres, and Realtime APIs for better DX"
expected = "Standardize Error Responses across APIs"

response = evaluator(output, expected, input=page_content)

print(f"Score: {response.score}")
print(f"Metadata: {response.metadata}")

TypeScript

import { LLMClassifierFromTemplate } from "autoevals";

(async () => {
  const promptTemplate = `You are a technical project manager who helps software engineers generate better titles for their GitHub issues.
You will look at the issue description, and pick which of two titles better describes it.

I'm going to provide you with the issue description, and two possible titles.

Issue Description: {{input}}

1: {{output}}
2: {{expected}}`;

  const choiceScores = { 1: 1, 2: 0 };

  const evaluator = LLMClassifierFromTemplate<{ input: string }>({
    name: "TitleQuality",
    promptTemplate,
    choiceScores,
    useCoT: true,
  });

  const input = `As suggested by Nicolo, we should standardize the error responses coming from GoTrue, postgres, and realtime (and any other/future APIs) so that it's better DX when writing a client,
We can make this change on the servers themselves, but since postgrest and gotrue are fully/partially external may be harder to change, it might be an option to transform the errors within the client libraries/supabase-js, could be messy?
Nicolo also dropped this as a reference: http://spec.openapis.org/oas/v3.0.3#openapi-specification`;
  const output = `Standardize error responses from GoTrue, Postgres, and Realtime APIs for better DX`;
  const expected = `Standardize Error Responses across APIs`;

  const response = await evaluator({ input, output, expected });

  console.log("Score", response.score);
  console.log("Metadata", response.metadata);
})();

Score results

Every scorer returns a small Score result object. This is the public surface consumers should read when they need to store, compare, or export evaluation results:

  • name: the scorer name
  • score: a number between 0 and 1, or None / null when the evaluation is skipped
  • metadata: optional scorer-specific details, such as rationale text or a selected choice. Keys are scorer-specific; consumers should not assume metadata keys are shared across scorer types.
  • error: deprecated and retained for backward compatibility; some scorers may still populate it, but callers should primarily handle thrown exceptions

Inputs, expected values, model prompts, and other runtime context are not part of the Score object. Keep those separately if your application needs them.

Creating custom scorers

You can also create your own scoring functions that do not use LLMs. For example, to test whether the word 'banana' is in the output, you can use the following:

Python

from autoevals import Score

def banana_scorer(output, expected, input):
    return Score(name="banana_scorer", score=1 if "banana" in output else 0)

input = "What is 1 banana + 2 bananas?"
output = "3"
expected = "3 bananas"

result = banana_scorer(output, expected, input)

print(f"Banana score: {result.score}")

TypeScript

import { Score } from "autoevals";

const bananaScorer = ({
  output,
  expected,
  input,
}: {
  output: string;
  expected: string;
  input: string;
}): Score => {
  return { name: "banana_scorer", score: output.includes("banana") ? 1 : 0 };
};

(async () => {
  const input = "What is 1 banana + 2 bananas?";
  const output = "3";
  const expected = "3 bananas";

  const result = bananaScorer({ output, expected, input });
  console.log(`Banana score: ${result.score}`);
})();

Why does this library exist?

There is nothing particularly novel about the evaluation methods in this library. They are all well-known and well-documented. However, there are a few things that are particularly difficult when evaluating in practice:

  • Normalizing metrics between 0 and 1 is tough. For example, check out the calculation in number.py to see how it's done for numeric differences.
  • Parsing the outputs on model-graded evaluations is also challenging. There are frameworks that do this, but it's hard to debug one output at a time, propagate errors, and tweak the prompts. Autoevals makes these tasks easy.
  • Collecting metrics behind a uniform interface makes it easy to swap out evaluation methods and compare them. Prior to Autoevals, we couldn't find an open source library where you can simply pass in input, output, and expected values through a bunch of different evaluation methods.

Documentation

The full docs are available for your reference.

Contributing

We welcome contributions!

To install the development dependencies, run make develop, and run source env.sh to activate the environment. Make a .env file from the .env.example file and set the environment variables. Run direnv allow to load the environment variables.

To run the tests, run pytest from the root directory.

Send a PR and we'll review it! We'll take care of versioning and releasing.

0.3.0 Jun 09, 2026
0.2.0 Apr 02, 2026
0.1.0 Feb 13, 2026
0.0.130 Sep 08, 2025
0.0.129 May 13, 2025
0.0.127 Apr 09, 2025
0.0.126 Mar 25, 2025
0.0.125 Mar 25, 2025
0.0.124 Mar 19, 2025
0.0.123 Mar 10, 2025
0.0.122 Mar 07, 2025
0.0.121 Mar 01, 2025
0.0.120 Feb 25, 2025
0.0.119 Feb 01, 2025
0.0.118 Jan 24, 2025
0.0.117 Jan 16, 2025
0.0.116 Jan 15, 2025
0.0.115 Jan 11, 2025
0.0.114 Jan 10, 2025
0.0.113 Jan 07, 2025
0.0.112 Jan 03, 2025
0.0.111 Dec 16, 2024
0.0.110 Dec 13, 2024
0.0.109 Dec 10, 2024
0.0.108 Dec 02, 2024
0.0.107 Nov 25, 2024
0.0.106 Nov 21, 2024
0.0.105 Nov 19, 2024
0.0.104 Nov 15, 2024
0.0.103 Nov 12, 2024
0.0.101 Nov 04, 2024
0.0.100 Oct 27, 2024
0.0.99 Oct 18, 2024
0.0.98 Oct 16, 2024
0.0.97 Oct 15, 2024
0.0.96 Oct 11, 2024
0.0.95 Oct 09, 2024
0.0.94 Oct 01, 2024
0.0.93 Oct 01, 2024
0.0.92 Sep 26, 2024
0.0.91 Sep 24, 2024
0.0.90 Sep 19, 2024
0.0.89 Sep 04, 2024
0.0.88 Sep 04, 2024
0.0.87 Aug 30, 2024
0.0.86 Aug 26, 2024
0.0.85 Aug 07, 2024
0.0.84 Aug 07, 2024
0.0.83 Aug 02, 2024
0.0.82 Aug 01, 2024
0.0.81 Jul 23, 2024
0.0.80 Jul 19, 2024
0.0.79 Jul 17, 2024
0.0.78 Jul 17, 2024
0.0.77 Jul 17, 2024
0.0.76 Jul 09, 2024
0.0.75 Jul 05, 2024
0.0.74 Jul 01, 2024
0.0.73 Jun 29, 2024
0.0.72 Jun 25, 2024
0.0.71 Jun 18, 2024
0.0.70 Jun 13, 2024
0.0.69 Jun 12, 2024
0.0.68 May 28, 2024
0.0.67 May 24, 2024
0.0.66 May 24, 2024
0.0.65 May 18, 2024
0.0.64 Apr 26, 2024
0.0.63 Apr 25, 2024
0.0.62 Apr 24, 2024
0.0.61 Apr 17, 2024
0.0.60 Apr 16, 2024
0.0.59 Apr 16, 2024
0.0.58 Apr 16, 2024
0.0.57 Apr 16, 2024
0.0.56 Apr 09, 2024
0.0.55 Apr 02, 2024
0.0.54 Mar 28, 2024
0.0.53 Mar 17, 2024
0.0.52 Mar 17, 2024
0.0.51 Mar 14, 2024
0.0.50 Mar 07, 2024
0.0.49 Mar 05, 2024
0.0.48 Feb 25, 2024
0.0.47 Feb 23, 2024
0.0.46 Feb 04, 2024
0.0.45 Jan 23, 2024
0.0.44 Jan 11, 2024
0.0.43 Jan 11, 2024
0.0.42 Jan 10, 2024
0.0.41 Dec 31, 2023
0.0.40 Dec 18, 2023
0.0.39 Dec 18, 2023
0.0.38 Dec 16, 2023
0.0.37 Dec 16, 2023
0.0.36 Dec 15, 2023
0.0.35 Dec 15, 2023
0.0.34 Dec 06, 2023
0.0.33 Dec 05, 2023
0.0.32 Nov 28, 2023
0.0.31 Nov 10, 2023
0.0.30 Nov 09, 2023
0.0.29 Nov 08, 2023
0.0.28 Nov 03, 2023
0.0.27 Nov 03, 2023
0.0.26 Oct 17, 2023
0.0.25 Oct 13, 2023
0.0.24 Oct 12, 2023
0.0.23 Oct 11, 2023
0.0.22 Sep 20, 2023
0.0.21 Sep 13, 2023
0.0.20 Sep 13, 2023
0.0.19 Sep 13, 2023
0.0.18 Sep 06, 2023
0.0.17 Sep 06, 2023
0.0.16 Sep 05, 2023
0.0.15 Sep 05, 2023
0.0.14 Aug 24, 2023
0.0.13 Aug 18, 2023
0.0.12 Aug 18, 2023
0.0.11 Aug 17, 2023
0.0.10 Aug 17, 2023
0.0.9 Aug 16, 2023
0.0.8 Aug 05, 2023
0.0.7 Jul 26, 2023
0.0.6 Jul 26, 2023
0.0.5 Jul 24, 2023
0.0.4 Jul 12, 2023
0.0.3 Jul 11, 2023
0.0.2 Jul 11, 2023
0.0.1 Jul 10, 2023

Wheel compatibility matrix

Platform Python 3
any

Files in release

Extras:
Dependencies:
chevron
jsonschema
polyleven
pyyaml