Catalog PyPI
Back to packageRELEASE DETAILS

0.72.0

PyPI

3tears-evals

Evaluate LLM-backed products: campaigns over levers, judged and code-graded trials, cost and latency accounting, and analysis reports

Published20 Oct 2026
Direct dependencies3
Transitive dependenciesNot calculated

README

Version 0.72.0 documentation

3tears-evals

Evals for LLM features, from a classifier to a tool-using agent: it runs each version over the same cases and says what moved, with the uncertainty that says whether the move is real. Python 3.14+.

pip install 3tears-evals

Rung 0 is one TOML file and no Python. examples/1-triage/triage.toml triages 30 support emails, each with the triage a person gave it, three times each:

# Rung 0, no Python: python -m threetears.evals triage.toml
cases = "emails.jsonl"
grader = ["category", "urgent", "needs_human"]
recording = "recordings/triage-toml.jsonl"
k = 3

[runner]
model = "deepseek/deepseek-v4-flash"
prompt = "Triage this support email:\n\n{email}"

[runner.output]
category = ["billing", "bug", "account", "sales", "spam"]
urgent = "bool"
needs_human = "bool"

python -m threetears.evals examples/1-triage/triage.toml replays the recorded model, offline and free, and its first line says how it went:

triage: 16/30 cases passed; 14 misses: gdpr-delete, nonprofit, phish-suspend, phish-invoice, crash-at-checkout, and 9 more

Below it come each field's pass rate, each category label's precision and recall, the top misses with why each missed, and where its report page is. Then climb the ladder, one idea per rung:

RungExampleClimb it when
11-triage/triage.pyPoint it at your own function: 15 lines of Python.
22-replies/When no code can grade the answer, let a model judge it, and check the judge against a person.
33-invoices/Changing a prompt? Compare it against the current one, and get a report you can hand to a reviewer.
44-booking/Is your agent doing the right thing to the world, not only saying it? Then serve your evals to the team.

Where the science lives:

Wiring it into your app (your store, your launcher, your world): Adopting the engine.

Install

pip install 3tears-evals is the base install. The FastMCP transport, for serving evals to an agent, is the [fastmcp] extra:

pip install "3tears-evals[fastmcp]"

To install a pre-release or an unreleased checkout, install from the repository at a tag instead:

pip install "3tears-evals @ git+https://github.com/pacepace/3tears.git@<tag>#subdirectory=packages/evals"

In a checkout of this repo, uv sync at the root does it, and the commands above run from packages/evals with uv run in front. threetears.evals.__version__ says which version is installed. The completion client (Model) is on the base install: it speaks each provider's HTTP API over httpx, with no SDK and no other 3tears package. The examples run on cheap models through OpenRouter (OPENROUTER_API_KEY); Model(id, provider="anthropic") (ANTHROPIC_API_KEY) and provider="openai" (OPENAI_API_KEY) are options, and base_url= takes any OpenAI-compatible endpoint. After a pip install, fetch the examples from the repository first (how).

The public API is still changing. From 0.70.0 only its host contract is promised: a name on it moves with a deprecation cycle, and any other declared name may change in any release, recorded in MIGRATIONS.toml. About 520 names are declared, mapped by rung; the rest a root exports are provisional (stability tiers).

What is different

  • A verdict, not a mean. Every version is run over the same frozen cases and tested case by case against a control, and evidence that cannot tell two versions apart says "not separated", never "no difference" (why).
  • Guardrails apart from capability. What a version must never do is decided on its own, so a gain cannot pay for a breach (why).
  • A judge is measured, not trusted. Every judged reading carries the evidence tier its judge's agreement with people and with itself reached (how).
  • An agent is graded on the world it leaves, a world your app declares, with checks proven to beat doing nothing and a conformance kit your app runs against its own world (what is new).

Docs

These links are relative to the package, so on GitHub each opens the page at the ref you are reading; on PyPI, where this README is the package's description, they do not resolve, so read the docs in the repository at your tag.

Climb

  • Building an inventory: what to test before a line of code, ending in rung 0; then which cases a classifier needs, and how many.
  • The ladder: rungs 1 to 4, through the four examples.
  • Concepts: the six concepts, and the glossary of every other word.

Go deeper

Background and reference

  • Design: the principles the engine keeps, why each concept is shaped as it is, and the prior art.
  • Open problems: known gaps.
  • The surface: the declared names on one page, by rung.
  • Reference: every declared name, setting, report field, goal-check builtin and action, generated from the code.

For experts

CapabilityAPIDocExample
World contractWorld(State, tools=[...]), each case's world key, expression graders; on a host, WorldRegistryEvaluating a tool-using agent4-booking/
World conformance kitcheck_world_conformance (threetears.evals.kernel.host)Step 5
Guardrails, decided apart from capabilitygrader(fn, guard=...), Judge(guard={dim: ...}), Result.guardrails(); on a host, MetricDescriptor(guardrail=True), RubricDim(axis="boundary")Reading the guardrails3-invoices/
Equivalence, the only verdict that says "good enough"grader("label", margin=0.05), grader(fn, margin=...), grader(rating, range=(1, 5)); on a host, MetricDescriptor.materiality_threshold and value_rangeReading a comparison3-invoices/
Typed verdicts and a CI gateResult.verdicts(), Result.gate(), python -m threetears.evals gate --fail-on regressed,breachedgate3-invoices/
Grids of factorsarms named as k=v pairs ("prompt=v2, effort=low"), Result.againstStart from the question3-invoices/
Campaigns and declared designscreate_campaign, update_campaign, add_runs_to_campaign, declared_design, exploratory, control_from_run_idDeclare the design
Cost against qualityAnswer, max_cost_usd=, the frontierCost and budgets, the frontier
Judge calibration and evidence tiersJudge(labels=...), rate_result, judge_agreement, JudgeEvidenceTierJudges and calibration2-replies/
Analysis written by a model over frozen evidencegenerate_analysisHaving a model write the analysisllm_analysis.py
CassettesWorld(tools=[...], recording=...); on a host, cassette_mode="capture" / "replay"Step 4, on a host
MCPthreetears.evals.actions, mount_fastmcp (extra fastmcp)Serving4-booking/serve.py
Keeping runsEval(...).run(store=path) (by default .evals/evals.sqlite); any DocumentStore, proven with STORE_CONFORMANCE_CASESKeep your runs, the store
A complete hostEvalHost, HostProfile, CandidateKindAdopting the enginecourierhost, then toyhost

Import only from the public roots the reference lists: a module below a root is internal and may move. A public name that leaves a root is recorded with its new home in each release's notes (Upgrading: names that move).

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Declared dependencies 3

Native requirements
3 direct targetsNot calculated transitive count
Package / targetRequirementRelationship
httpx
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.14",
  "evaluation": "NOT_EVALUATED"
}
httpx>=0.27runtime
pydantic
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.14",
  "evaluation": "NOT_EVALUATED"
}
pydantic>=2.0runtime
fastmcp
Environment
{
  "extras": "",
  "marker": "extra == \"fastmcp\"",
  "requires_python": ">=3.14",
  "evaluation": "NOT_EVALUATED"
}
fastmcp<4,>=3.4.2; extra == "fastmcp"runtime

Distribution files

2 collected
3tears_evals-0.72.0-py3-none-any.whl

bdist_wheel · 2,351.19 KB · Python py3

Source file
3tears_evals-0.72.0.tar.gz

sdist · 4,190.31 KB · Python source

Source file

Repository

ACCESSIBLE
pacepace/3tears

Shared repository data · GitHub

License detected in repository
MIT
License branch / ref
develop
Last push
20 Oct 2026
Archived
No
Contributor identities
— · partial collection

Public sponsor counts have not been collected. These signals belong to the repository owner.

Downloads & popularity

0count
Gauge · observed snapshots20 Oct 2026
10.50
2026-10-20: 0 · observed 2026-10-20T17:18:19.8928356Z
20 Oct20 Oct

github · 1 observations shown. Missing days are unknown.

View observed values
Date / source periodValueObserved at
2026-10-2002026-10-20T17:18:19.8928356Z

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 15:37 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package_version:010df05c70c79baea6cfddcb341cebfcc99ad1a5ff4d2b25ce148983970205c1

Other collected versions

View all collected versions →