Automated GL coding & invoice routing (Beta)

Task: given an invoice's text (sender, product, description) and its company, predict three things a finance team would otherwise fill in by hand:

  1. Processor โ€” which employee should handle it (~63 candidates per company)
  2. Acceptor โ€” who approves it (~10 candidates per company)
  3. GL code โ€” the accounting category (32 codes)

Processor and acceptor are company-scoped cross-table link predictions (invoice โ†’ employee), the kind of high-cardinality target that plain bag-of-features models handle poorly. Aito predicts each independently from the invoice text and company alone โ€” the targets are never inputs.

Methods. Aito is measured with both engines โ€” v1 (rep1 / TableDb, /api/v1) and v2 (rep2 / CollectionDb, /api/v2) โ€” from the InvoiceRoutingEvaluation booktest. Baselines are a tuned scikit-learn Random Forest, LightGBM (with a company-local class-index encoding) and FLAML AutoML, on the identical 200-row held-out test set; reproduction scripts and method notes live in tasks/generated-invoice-benchmark/.

Top-1 accuracy (10k training rows, 200-row test)

TargetRFLightGBMAito v1Aito v2
GL code (32 classes)60.0%46.5%84.5%83.0%
Processor (high-cardinality link)6.5%0.0%11.0%9.0%
Acceptor (link)29.0%48.0%32.0%24.5%

Read honestly:

  • GL code โ€” Aito wins decisively on both engines (~83โ€“85% vs 60% / 47%). The field-level priors carry the low-cardinality target well.
  • Processor โ€” the hard cross-table target, where the tree models nearly collapse (LightGBM's local-index encoding drops to 0% at this scale). Aito leads on both engines, modestly (11% / 9%).
  • Acceptor โ€” the one target Aito loses: LightGBM's local index works when there are only ~10 candidates, reaching 48% vs Aito's 32% / 24.5%. Honest benchmarks include the cases you lose.

v1 vs v2: top-1 is close, but v2 ranks far better

Top-1 accuracy understates the v2 engine. On the link-heavy targets, v2's cross-table link priors rank the true candidate dramatically higher than v1, even where top-1 is a touch lower:

Targetv1 mean rankv2 mean rank
Acceptor23.93.7
Processor125.234.2
GL code2.02.6

For acceptor, v2 puts the correct employee in the top ~4 on average (vs ~24 for v1); for processor, top ~34 out of ~63 (vs ~125). The link/property signal is clearly there โ€” the remaining gap is the final top-1 calibration/tie-break, which is exactly where rep2 is still being tuned (v2 is in public beta). So on these targets v2 is better positioned than the top-1 number suggests, and closing the calibration gap is the active work.

The number that isn't accuracy: training time

MethodTime to absorb new data (update the model)
Aito (v1 or v2)0 s โ€” incremental; new rows are queryable immediately
Random Forest~100 s (full refit)
LightGBM~40 min (full refit)
FLAML AutoMLbudgeted โ€” default 1,200 s per target

This is the part a top-1 table hides. Every baseline needs a retraining pipeline to absorb new invoices; Aito absorbs them on insert, with a $why explanation behind every prediction. On a workload where routings change weekly, "0 s and explainable" competes hard with "a few points more, but retrain nightly and serve a separate model."

How to read this

  • Aito wins on GL code and on the hard cross-table processor target, and is a couple of points off on acceptor โ€” with no training and full explanations.
  • v2 vs v1: top-1 is close; v2 ranks the true candidate much higher (the link priors are strong), and its remaining top-1 gap is a known, active calibration item.
  • Statistics: n=200 test set (95% CI โ‰ˆ ยฑ7pp at 50%), single synthetic-data seed. Read the direction โ€” which method handles which target โ€” as the durable signal; treat individual cells as point estimates.

Generated. Aito's figures are interpolated at docs-build time from the InvoiceRoutingEvaluation compare-* booktest snapshots (via a metrics.json the docs generator produces), so they update whenever the evaluation is re-baselined and can't silently drift. RF / LightGBM / FLAML are from the published Python baselines. Multi-scale numbers (1k / 100k) are a follow-up.