Skip to main content

Heartcut

CI License: MIT Python 3.11+

Replace an expensive LLM classifier with a tiny model that keeps most of its accuracy at a fraction of the cost and latency. Heartcut labels your data with a teacher LLM, trains compact students on those labels, benchmarks teacher and students on the same human-labeled test set, and serves the winner on a CPU.

Most teams now call an LLM API for simple, high-volume tasks such as ticket routing or intent tagging. Heartcut is a repeatable way to measure, and then cut, that bill.

The name comes from distilling: the heart cut is the clean middle of the run that the distiller keeps. Heartcut keeps the part of the LLM your task needs and leaves the expensive rest behind.

Results

No benchmark results yet. This block is written by heartcut report from results/<experiment>/results.json, and only from that file, so the README can never show a number the benchmark did not produce. Simulated-teacher runs are refused.

How it works

The pipeline diagram is in the README on GitHub.

The benchmark is the core deliverable; the serving stack exists to prove that the student's cost and latency numbers hold outside a notebook.

Stage Command What it does
Data heartcut data Loads Banking77 / CLINC150 (or your task) into id, text, label; deterministic splits; moves train/validation labels to a hidden table.
Label heartcut label Sends the unlabeled pool (and the test split, to score the teacher) to the teacher. Async, rate-limited, retried, cached by prompt hash, budget-capped; logs tokens and dollars per call. --dry-run estimates the cost first; --offline guarantees zero spend.
Audit heartcut audit Teacher labels vs. the hidden human labels: accuracy, per-class errors, top confusions, agreement vs. correctness, effect of the confidence filter.
Train heartcut train Three student tiers × labeling budgets × seeds, on teacher labels only, logged to MLflow. Hard or soft (distillation) labels.
Benchmark heartcut benchmark Everything on the human-labeled test set: one table, a Pareto chart, a learning curve, error analysis, routing analysis, model card.
Export heartcut export Best student (chosen on teacher-labeled validation data) to ONNX with dynamic int8 quantisation, parity-checked against the original.
Serve heartcut serve FastAPI on CPU, optional fallback to the teacher below a confidence threshold.

Install

Requires Python 3.11+.

pip install "heartcut[all]"     # every stage, including PyTorch for the neural students
pip install "heartcut[serve]"   # only serve an exported student: ONNX Runtime, no PyTorch

The extras (pipeline, teachers, students, export, serve, tracking, demo) can be combined; pyproject.toml lists what each one installs. The ready-made experiment configs and prompts live in this repository, so the quickstart below runs from a clone.

Quickstart

Requires uv.

git clone https://github.com/Amir-Parsian/Heartcut && cd Heartcut
uv sync --all-extras

# 1. Free smoke run: the whole pipeline on a Banking77 slice with the simulated teacher.
make smoke

# 2. Reproduce the published benchmark from cached teacher labels (no API spend).
make labels-pull LABELS_REPO=<user>/heartcut-banking77-labels
make benchmark && make report

# 3. Or label with a real teacher yourself.
export ANTHROPIC_API_KEY=...                  # keys come from the environment only
make label-dry-run                            # cost estimate, no calls
make label && make audit && make benchmark

Any config value can be changed from the command line, e.g. a cheaper teacher and a 200-example development slice:

uv run heartcut label -c configs/experiments/banking77.yaml \
    --set teacher=configs/teachers/claude-haiku-5-5.yaml \
    --set dataset.max_examples.train=200

What is compared

Tier Model Size Notes
Teacher Claude via the Anthropic API, or an open-weights model behind an OpenAI-compatible server (vLLM, Ollama) hosted / 7B JSON-schema-constrained answers; optional self-consistency voting
Baseline TF-IDF word + char n-grams, logistic regression a few MB sub-millisecond on CPU
Small SetFit-style: contrastive fine-tuning of all-MiniLM-L6-v2 + logistic-regression head 22M params
Medium distilbert-base-uncased fine-tuned end to end 66M params ModernBERT config included

Datasets: Banking77 (13,083 banking queries, 77 intents) is the primary benchmark; CLINC150 (150 intents plus out-of-scope) is the second. The official test split with its human labels is the only ground truth for final scores. Training labels are hidden from training and used once, by the audit, to measure teacher label quality.

Benchmark rules

  • Every model is scored on the same human-labeled test set, on the same machine.
  • Students: mean and standard deviation over 3 seeds. The served row is the exported artifact (ONNX int8 for transformer students) of the seed with the best agreement with the teacher on teacher-labeled validation data. The test set never chooses anything.
  • Cost per 1,000 predictions. Teacher: logged API tokens × published price (prompt-cache reads and writes included). Student: CPU instance hourly price ÷ measured throughput.
  • Latency: single request p50/p95 after warm-up; throughput: batched, same CPU.
  • results.json records the hardware, library versions, git revision and the date of every price used. See docs/benchmark.md.

Serving

uv run heartcut export -c configs/experiments/banking77.yaml   # prints the export dir
docker build --build-arg MODEL_DIR=<export dir> -t heartcut-serve .
docker run --rm -p 8000:8000 heartcut-serve

curl -s localhost:8000/predict -H 'content-type: application/json' \
     -d '{"text": "My card still has not arrived"}'
# {"label": "card_arrival", "confidence": <float>, "latency_ms": <float>, "source": "student", ...}

POST /predict also takes {"texts": [...]} (up to 256). GET /health reports the model and router settings. The image contains no PyTorch: just ONNX Runtime, tokenizers and FastAPI. Set HEARTCUT_FALLBACK_THRESHOLD and HEARTCUT_TEACHER_CONFIG (build with --build-arg EXTRAS=serve,teachers) to send low-confidence predictions to the teacher; the benchmark's routing table shows what share of traffic that would be and the blended cost.

The Gradio demo shows student and teacher side by side with latency and cost per call, and deploys to Hugging Face Spaces.

Add your own task

A new dataset needs a config file and, if none of the built-in loaders fit, a loader function. No core code changes. See docs/adding-a-task.md and the worked example in examples/helpdesk.

Project layout

src/heartcut/
├── data/        loaders, common schema, deterministic splits, hidden labels
├── teachers/    prompts, Anthropic + OpenAI-compatible backends, cache, runner, pricing
├── students/    TF-IDF, SetFit-style, encoder fine-tune, training stage
├── eval/        metrics, label audit, cost model, latency bench, charts, report
├── serve/       ONNX export, CPU runtime, FastAPI app, fallback router
└── cli.py       Typer CLI, one command per stage
configs/         datasets, teachers, students, experiments, published prices
prompts/         prompt templates
demo/            Gradio app (Hugging Face Spaces)
examples/        a custom task end to end
results/         benchmark tables and charts (committed)
docs/            design notes, methodology, guides, blog post draft

Development

make install     # all extras + pre-commit hooks
make lint typecheck test

CI runs ruff, strict mypy and the tests (coverage gate: 80% of src/) on Python 3.11 and 3.12, then builds the Docker image and calls /predict on it. CI never calls a paid API: teacher tests use mocked HTTP transports and a simulated teacher. Design decisions and their trade-offs are in docs/design.md.

Status

v0.1.0 contains the full pipeline, tests and CI. Definition of done for v1.0.0:

  • make benchmark reproduces every reported number from cached labels on a clean machine (implemented; needs the first real labeling run and published labels)
  • Best student within 3 accuracy points of the teacher on Banking77 test, or the README explains the gap (needs results)
  • Student p95 under 50 ms per request on a standard 4-core CPU (needs results)
  • Docker image builds and serves /predict in CI
  • CI green with 80%+ coverage on src/ (about 96%)
  • Live demo link, results table and Pareto chart in this README
  • Adding a new dataset needs only a config and a loader, shown in a guide

License and data

Code: MIT. Banking77 is released by PolyAI under CC BY 4.0; CLINC150 by Clinc under CC BY 3.0. Teacher labels published by this project keep the source texts' licenses; confirm redistribution terms before making a labels dataset public.

Metadata

Release files for heartcut 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for heartcut 0.1.0
File Size Uploaded Provenance Actions
heartcut-0.1.0.tar.gz 498.7 kB With provenance Details for heartcut-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for heartcut 0.1.0
File Interpreter ABI Platform Actions
heartcut-0.1.0-py3-none-any.whl Python 3 none any Details for heartcut-0.1.0-py3-none-any.whl

Total release size: 594.3 kB

Release files / heartcut-0.1.0.tar.gz

Download URL heartcut-0.1.0.tar.gz
Size 498.7 kB
Tags Source
SHA-256 checksum
How to use checksums
4347acf3e15b45a5fddeacbd9a386e489515f9793a33cd9936bcfefaad3fa499
BLAKE2b-256 checksum
How to use checksums
8bb78d04cc3b5752b1b322df8742eeb33a9cb1aa963fe5150457052b91dee42d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.

Transparency log

Release files / heartcut-0.1.0-py3-none-any.whl

Download URL heartcut-0.1.0-py3-none-any.whl
Size 95.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9f90bead8041dd8b0dd9ceb9aafc8410ca6a45f6ddcb357d0397f60b13376431
BLAKE2b-256 checksum
How to use checksums
29bf87bd40cf48334d35ef15681f2b8c78270b6bb40edac7c3b24b5023cb1c83
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.

Transparency log

Security for heartcut 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for heartcut-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page