Skip to main content

An LLM reliability + accuracy benchmark for real fundraising documents -- because LLMs are probabilistic and finance needs determinism.

Project description

Probity

CI License: MIT Python 3.9+

Probity demo — the same question asked 20 times, same clause, same model, flipping between pre-money and post-money

LLMs are fundamentally probabilistic. Ask one the same question twice and you can get two different answers — that's not a bug, it's how sampling works. Most of the time that's fine. It is not fine when the question is "is this a pre-money or post-money valuation" and the answer decides who owns what in a startup financing. Finance needs determinism; LLMs supply probability. Nobody was measuring that gap, so Probity does: it benchmarks how often a model's answer wobbles on real term sheets, charters, SAFEs, convertible notes, and cap tables — before you ever get to whether the answer is right.

  • Wobble (the core metric) — does the model give the same answer when you ask it the same question 20 times at temperature 0.7? A model whose answer flips run to run cannot be trusted in a workflow that touches money, even when it is often right. This is label-free: it needs no ground truth, only repetition.
  • Accuracy — does the model get the answer right, graded against a validated answer that a human extracted from the source document (not authored by an AI)?

These are scored separately and never averaged into one headline — a model can be perfectly consistent and consistently wrong. Models are run across a size ladder (1B → 12B local, plus a hosted model) to test whether wobble falls as capability rises. Heavier models (a 27B local model and hosted frontier models) are reserved for a single comprehensive sweep once every test is built.

Quickstart

Option A — install the package (fastest way to run a real benchmark yourself)

pip install probity-bench
probity-bench onboard   # pick documents to fetch, models to run, and store your API key(s)

onboard is a guided wizard — same idea as openclaw onboard or claude setup: it walks you through which leaves to pull real SEC documents for, which models to benchmark (auto-detects local Ollama models; DeepSeek/Gemini for hosted), and collects + verifies any API key by making one real call before it lets you proceed. Everything is stored locally at ~/.probity/ — nothing leaves your machine except the model calls you explicitly configure.

Probity onboarding — documents, models, and API key setup, all local

The package ships the full pipelineengine/, all 60 leaves' code, oracles, and prior results — everything except the raw SEC documents themselves (fetch those via onboard or source.py, per leaf) and, obviously, no model weights (those come from Ollama/DeepSeek/Gemini).

probity-bench demo       # zero-config: replay a real wobble example, no install/network needed
probity-bench results    # print the 2 summary tables from bundled scored.json
probity-bench list       # every leaf + whether you've fetched its corpus
probity-bench run <leaf> # fetch (if needed) + benchmark one leaf with your configured models

Option B — clone the repo (full reproducibility, no package boundary)

git clone https://github.com/eikiyo/probity.git
cd probity
make setup     # runs the test suite + regenerates results/RESULTS.md + this README's tables from disk

That's it — zero third-party dependencies, pure Python 3 stdlib, no network call, no API key. (No make? python3 -m unittest discover -s tests && python3 results/render.py does the same thing.)

To re-run a test yourself against live models (needs Ollama running gemma3:1b locally + a DeepSeek API key — see .env.example):

cp .env.example .env && set -a && source .env && set +a
cd leaves/vesting_schedule       # or any other leaf under leaves/
python3 source.py                # fetch the real SEC documents into corpus/
python3 run.py                   # run the model ladder, N=20 each, writes scored.json
python3 ../../results/render.py  # regenerate the tables with your fresh numbers

Benchmark results

60 tests, each item run 20x/item at temp 0.7 across a model size ladder. Wobble (lower = better) is the run-to-run inconsistency rate, weighted by item count across every test that model ran. Full per-test breakdown (all 60 tables): results/RESULTS.md.

Does reliability improve with model size?

Model Size Tests covered Wobble Accuracy
deepseek-v4-flash hosted 58 6% 95%
gemma3:1b 1B, local 51 44% 54%
llama3.2:latest 3B, local 1 56% 81%
gemma4:12b 12B, local 1 0% 100%

By fundraising-document category

Category Tests Wobble ↓ (deepseek) Accuracy (deepseek)
Priced equity rounds 16 5% 90%
SAFEs & convertible notes 12 4% 100%
Cap table math 7 6% 94%
Investor rights & governance 7 6% 95%
Founder & employee vesting 5 2% 98%
Regulatory disclosures 5 15% 100%
Off-market risk flags 5 8% 92%
Exit waterfalls 1 25% 100%

Full per-item breakdown — including which clauses make each model wobble — in results/RESULTS.md.

Why the answers are trustworthy

Most LLM benchmarks in niche domains are built from synthetic data with synthetic answers. That has a hidden flaw: if an AI writes both the question and the answer key, the answer key can be wrong in exactly the ways the model under test is wrong. Probity avoids this with a strict oracle layer:

  1. Source a real document that contains the ground truth in its own authoritative text — for example, a Certificate of Incorporation filed with the SEC that states, in legally precise language, whether its preferred stock is participating.
  2. A human separates the question from the answer. The model sees only the clause (the question). The validated label, plus the exact quote that proves it, is stored in a separate oracle file the model never sees. Items whose answer cannot be determined with confidence are excluded, not guessed.
  3. Run only the question through each model, N times, and score the majority answer against the validated label.

Synthetic instantiation is used only to multiply difficulty (varying numbers, off-market terms, ambiguous phrasing) on top of a real, human-validated seed — never as the sole source of truth.

The test map

Probity's full test backlog is a structured map of fundraising-reasoning capabilities (engine/registry.json) — 67 atomic checks across priced equity, convertibles, cap-table math, exit waterfalls, investor rights, founder equity, regulatory filings, and off-market risk flags. Each check is built one at a time, to depth, against real sourced documents.

Structure

engine/    the model-agnostic core: clients, run harness, normalizer, reliability+accuracy scorers
leaves/    one folder per test, each with its real-document corpus, its separated oracle, and its runner
results/   the living benchmark table

See the Quickstart above for the full clone → run → reproduce path.

Contributing

Bug reports, new leaves, and sourcing improvements are welcome — see CONTRIBUTING.md. Security issues: see SECURITY.md, never a public issue.

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

probity_bench-1.1.0.tar.gz (1.1 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

probity_bench-1.1.0-py3-none-any.whl (1.3 MB view details)

Uploaded Python 3

File details

Details for the file probity_bench-1.1.0.tar.gz.

File metadata

  • Download URL: probity_bench-1.1.0.tar.gz
  • Upload date:
  • Size: 1.1 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for probity_bench-1.1.0.tar.gz
Algorithm Hash digest
SHA256 8317dcab9940c75fc2d931315bc4861ede2de8cc63ff370cc83552ce349b34e4
MD5 42d8de85077b60c42ac90b768ee1dbba
BLAKE2b-256 2b27cdcd13c0c598d43a7c158544d6228d8b1bbd8c2ae6c92546d687c87c56f3

See more details on using hashes here.

File details

Details for the file probity_bench-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: probity_bench-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 1.3 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for probity_bench-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 070f0c4986ebbd9caa39e81925c1e83538cd4b52ec68eda25318cd5cff9ddf52
MD5 c727a4e3525f7f87e4c6f2cd0998a6e5
BLAKE2b-256 69da59045c03e4752133919be79adff02a596b3125435e9943c32e139b54579b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page