Evaluator SDK Basics

Score AI outputs against built-in eval templates with fi.evals: judged checks, deterministic checks, and batch loops with the Evaluator class.

📝
TL;DR

Initialize the Evaluator class from fi.evals, then run built-in eval templates against real support replies: a judged context-adherence check, a deterministic JSON check, a PII screen, and a batch conciseness pass. Each call returns an output (a score or a pass/fail verdict, depending on the template) and a reason.

TimeDifficultyPackage
15 minBeginnerai-evaluation
Prerequisites

Install

pip install ai-evaluation
export FI_API_KEY="your-api-key"
export FI_SECRET_KEY="your-secret-key"

Tutorial

Initialize the evaluator

import os
from fi.evals import Evaluator

evaluator = Evaluator(
    fi_api_key=os.environ["FI_API_KEY"],
    fi_secret_key=os.environ["FI_SECRET_KEY"],
)

No output to check here. The Evaluator instance is what every later step calls .evaluate() on.

Score a support reply for context adherence

context_adherence is a judged template: it needs a model_name to act as the grading model.

support_context = (
    "Refunds are issued within 5-7 business days to the original payment method. "
    "Store credit is available immediately as an alternative."
)
support_reply = "You'll get your refund back on the original card within 5 to 7 business days."

result = evaluator.evaluate(
    eval_templates="context_adherence",
    inputs={"context": support_context, "output": support_reply},
    model_name="turing_flash",
)

item = result.eval_results[0]
print(item.output)
print(item.reason)

You should see something like this (illustrative, exact wording varies by run):

0.92
The response accurately reflects the refund timeline stated in the context.

item.output is the 0-1 adherence score, item.reason is the grading model’s explanation.

Run a deterministic check with no judge model

Deterministic templates don’t grade with a model. Pass eval_templates and inputs only, no model_name.

order_confirmation = '{"order_id": "SO-48213", "status": "shipped", "refund_issued": false}'

result = evaluator.evaluate(
    eval_templates="is_json",
    inputs={"text": order_confirmation},
)

print(result.eval_results[0].output)

You should see:

Passed

Screen a customer message for PII

pii is a judged safety template. Run it on inbound text before it reaches a log or a downstream store.

customer_message = "My order number is SO-48213 and my name is Jordan Reyes."

result = evaluator.evaluate(
    eval_templates="pii",
    inputs={"input": customer_message},
    model_name="turing_flash",
)

item = result.eval_results[0]
print(item.output)
print(item.reason)

You should see the check fail the message and name what it found (illustrative):

Failed
The message contains a personal name (Jordan Reyes) and an order identifier.

Batch-score replies for conciseness

Loop evaluate() over a list of candidate replies and compare scores directly.

support_replies = [
    "Your refund will be back on your card within 5 to 7 business days after we process the return.",
    "Sure, no problem at all, happy to help, let me just check on that for you real quick, one moment please.",
]

for reply in support_replies:
    result = evaluator.evaluate(
        eval_templates="is_concise",
        inputs={"output": reply},
        model_name="turing_flash",
    )
    item = result.eval_results[0]
    print(f"{item.output!s:<8} {reply[:50]}")

You should see the first reply pass and the second fail on filler (illustrative):

Passed   Your refund will be back on your card within 5 
Failed   Sure, no problem at all, happy to help, let me

The second reply fails on filler. Tighten it and rerun the same check:

tightened_reply = "Your refund will be back on your card within 5 to 7 business days."

result = evaluator.evaluate(
    eval_templates="is_concise",
    inputs={"output": tightened_reply},
    model_name="turing_flash",
)
item = result.eval_results[0]
print(f"before: Failed")
print(f"after:  {item.output!s}")

You should see the failure close:

before: Failed
after:  Passed

Catch evaluation errors before they reach production

Wrap evaluate() so a bad template name or a transient API error doesn’t crash a batch job.

def score_reply(template, output, **extra_inputs):
    try:
        result = evaluator.evaluate(
            eval_templates=template,
            inputs={"output": output, **extra_inputs},
            model_name="turing_flash",
        )
        item = result.eval_results[0]
        return item.output, item.reason
    except Exception as exc:
        print(f"Eval '{template}' failed: {exc}")
        return None, None

status, reason = score_reply("toxicity", "I completely disagree, but I respect your view.")
print(status, reason)

You should see the toxicity check pass with no exception:

Passed The response is respectful and contains no toxic language.

The try/except here is what turns a bad template name into a logged failure instead of a stopped script.

Troubleshooting

SymptomCauseFix
AuthenticationError on evaluator.evaluate()FI_API_KEY or FI_SECRET_KEY missing or unexportedRe-run the export block in the current shell, then re-run the script
ModuleNotFoundError: No module named 'fi.evals'ai-evaluation not installed, or an unrelated fi package shadows itpip install ai-evaluation, and check pip show fi doesn’t point at a different package
evaluate() raises an unknown-template errorTypo in the eval_templates stringCheck the exact name against the built-in eval catalog
IndexError on result.eval_results[0]The call ran but returned no results, usually a rate limit or timeoutCheck result.eval_results is non-empty before indexing, retry the call, and lower max_workers on the Evaluator() constructor if you’re hitting rate limits
A judged template like context_adherence, pii, or is_concise errors out or scores every row the samemodel_name was left out, but judged templates require onePass model_name="turing_flash" for any non-deterministic, non-statistical template
A deterministic template like is_json raises a model-related errormodel_name was passed but isn’t needed for deterministic or statistical templatesDrop the model_name kwarg for those categories

Browse the full set of built-in templates in the built-in eval catalog.

Was this page helpful?

Questions & Discussion