Skip to main content

thomas

❖ Communityv0.1.0

Fine-tune a small calibrated encoder classifier on Modal and rate it with gonogo. Every GPU launch goes through the human approval gate with the exact config shown; data checks and evaluation run locally for free.

Open in Hermes Desktop
hermes plugins install thomas

What it adds

Tools 4

thomas_check_datathomas_encoder_trainthomas_run_statusthomas_encoder_eval

Hooks 1

pre_tool_call

README

From the reviewed commit 369aa76 ↗; it updates when the author re-pins.

thomas — a Hermes plugin

Train a small calibrated classifier on a Modal GPU and get a gonogo verdict on it, without leaving the conversation. Every GPU launch stops at Hermes' human approval gate with the exact config on screen. Checking the data and running the eval are local and free.

hermes plugins install keppy/hermes-plugin-thomas
hermes plugins enable thomas

Pairs with hermes-plugin-gonogo: thomas_encoder_eval saves a gonogo report JSON that gonogo_compare can pair against a baseline or a later model.

What it adds

Tool What it does Costs
thomas_check_data Validates a {text, label} JSONL: schema, label counts, thin labels, duplicates, conflicting labels free
thomas_encoder_train Fine-tunes an encoder on a Modal L4, temperature-scales it on a held-out split, pulls the artifact back. Runs in the background GPU time, gated
thomas_run_status running / done / failed, calibration numbers, log tail; lists runs with no argument free
thomas_encoder_eval CPU inference on held-out cases → gonogo verdict, operating point, calibration error free

Plus a pre_tool_call hook, the credit gate, and a bundled skill, thomas-encoder, that carries the procedure: check first, keep an eval split the model never saw, poll rather than relaunch, report the interval.

The credit gate

thomas_encoder_train is escalated to Hermes' approval gate on every call, by a hook that runs before the handler. The model can't skip it. The prompt looks like:

thomas: launch a PAID GPU fine-tune — johnnyboycurtis/ModernBERT-small-v2 on
cases.jsonl (9503 rows), 3 epochs, batch 32, lr 2e-05, calib 500, seed 7, L4 (Modal)

The allowlist key is a hash of that resolved config. So answering [a]lways approves that one config, and a different model, dataset or epoch count asks again. A non-interactive session with no approval bridge fails closed.

Contract

The plugin reads thomas artifacts against thomas's docs/CONTRACT.md: the confidence definition, the artifact layout, the split rules. It supports contract version 1 (thomas 0.2.x). An artifact with a newer contract_version in its metrics.json is refused with a message to update the plugin, rather than read wrong.

Setup

The plugin itself only needs gonogo-eval, which Hermes installs from pyproject.toml. Training and inference run in a separate Python so torch and Modal stay out of the Hermes venv:

git clone --branch v0.2.0 https://github.com/keppy/thomas && cd thomas
uv venv && uv pip install -e ".[encoder]"
.venv/Scripts/modal token new        # or .venv/bin/modal on macOS/Linux

Then set THOMAS_PYTHON to that interpreter in $HERMES_HOME/.env:

THOMAS_PYTHON=C:/Users/you/git/thomas/.venv/Scripts/python.exe

Runs live under $HERMES_HOME/thomas/runs/<run_name>/ (config.json, status.json, log.txt, artifact/). Set THOMAS_RUNS_DIR to put them somewhere else.

Checked against a real artifact

thomas_encoder_eval on the Banking77 canary artifact from the thomas repo (ModernBERT-small-v2, 250 held-out cases, target 95%):

AUTOMATE WITH REVIEW — overall pass rate 87.2% [82.5%, 90.8%] misses the 95% target,
but abstaining below confidence 0.91 reaches 98.3% precision on 71% of cases
Operating point: threshold 0.912, coverage 71.2%, 72 deferred, precision 98.3% [95.2%, 99.4%]
Calibration error 0.03
Note: The 0.91 threshold was chosen by searching this same case set, so its precision
is optimistically biased. Re-measure it on fresh cases before relying on it.

That's the same verdict as the gonogo example script run on the same artifact.

And a live run through the plugin itself, start to finish: thomas_check_data → thomas_encoder_train (approval gate) → Modal L4 → thomas_run_status → thomas_encoder_eval. The config was deliberately tiny (801 training rows, about 10 per label, 1 epoch), so the model is weak and the verdict says so:

DO NOT AUTOMATE — pass rate 15.2% [11.3%, 20.2%] is below 50%
(trained in 85 s; T = 0.60; calibration error 0.07; chance is 1.3% on 77 labels)

The first artifact pull hit Modal's stale-volume snapshot and the built-in retry recovered, which is why the retry is there. Confidence comes from thomas.encoder_train.scaled_softmax, the function the training run used to fit the temperature, so there's one definition end to end.

Development

pip install -e ".[dev]"
pytest
hermes plugins validate . && hermes plugins doctor .

The tests need no GPU, no Modal and no thomas install. Training is exercised with a fake runner subprocess, and the verdict is checked on canned predictions.

License

MIT

← Back to the catalog · catalog built Sep 26, 2026